diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:57 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:57 +0000 |
commit | 9508a382f8a9f241dab097d921b6d290c1c3a776 (patch) | |
tree | fa456480bae7040c3f971a70b390f2d091c680b5 /fb | |
parent | ded6147bfb5d75ff1e67c858040a628b61bc17d1 (diff) |
Initial revision
Diffstat (limited to 'fb')
-rw-r--r-- | fb/fb.h | 2018 | ||||
-rw-r--r-- | fb/fb24_32.c | 623 | ||||
-rw-r--r-- | fb/fb24_32.h | 49 | ||||
-rw-r--r-- | fb/fballpriv.c | 77 | ||||
-rw-r--r-- | fb/fbarc.c | 118 | ||||
-rw-r--r-- | fb/fbbits.c | 175 | ||||
-rw-r--r-- | fb/fbbits.h | 959 | ||||
-rw-r--r-- | fb/fbblt.c | 926 | ||||
-rw-r--r-- | fb/fbbltone.c | 865 | ||||
-rw-r--r-- | fb/fbbstore.c | 62 | ||||
-rw-r--r-- | fb/fbcmap.c | 668 | ||||
-rw-r--r-- | fb/fbcompose.c | 2897 | ||||
-rw-r--r-- | fb/fbcopy.c | 626 | ||||
-rw-r--r-- | fb/fbfill.c | 212 | ||||
-rw-r--r-- | fb/fbfillrect.c | 111 | ||||
-rw-r--r-- | fb/fbfillsp.c | 99 | ||||
-rw-r--r-- | fb/fbgc.c | 310 | ||||
-rw-r--r-- | fb/fbgetsp.c | 84 | ||||
-rw-r--r-- | fb/fbglyph.c | 472 | ||||
-rw-r--r-- | fb/fbimage.c | 364 | ||||
-rw-r--r-- | fb/fbline.c | 179 | ||||
-rw-r--r-- | fb/fboverlay.c | 449 | ||||
-rw-r--r-- | fb/fboverlay.h | 128 | ||||
-rw-r--r-- | fb/fbpict.c | 1167 | ||||
-rw-r--r-- | fb/fbpict.h | 976 | ||||
-rw-r--r-- | fb/fbpixmap.c | 378 | ||||
-rw-r--r-- | fb/fbpoint.c | 156 | ||||
-rw-r--r-- | fb/fbpush.c | 243 | ||||
-rw-r--r-- | fb/fbrop.h | 139 | ||||
-rw-r--r-- | fb/fbscreen.c | 297 | ||||
-rw-r--r-- | fb/fbseg.c | 723 | ||||
-rw-r--r-- | fb/fbsetsp.c | 100 | ||||
-rw-r--r-- | fb/fbsolid.c | 212 | ||||
-rw-r--r-- | fb/fbstipple.c | 312 | ||||
-rw-r--r-- | fb/fbtile.c | 200 | ||||
-rw-r--r-- | fb/fbtrap.c | 1382 | ||||
-rw-r--r-- | fb/fbutil.c | 361 | ||||
-rw-r--r-- | fb/fbwindow.c | 341 |
38 files changed, 19458 insertions, 0 deletions
diff --git a/fb/fb.h b/fb/fb.h new file mode 100644 index 000000000..48cf40d38 --- /dev/null +++ b/fb/fb.h @@ -0,0 +1,2018 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fb.h,v 1.35 2003/01/30 21:46:30 tsi 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. + */ + +#ifndef _FB_H_ +#define _FB_H_ + +#include "X.h" +#include "scrnintstr.h" +#include "pixmap.h" +#include "pixmapstr.h" +#include "region.h" +#include "gcstruct.h" +#include "colormap.h" +#include "miscstruct.h" +#include "servermd.h" +#include "windowstr.h" +#include "mi.h" +#include "migc.h" +#include "mibstore.h" +#ifdef RENDER +#include "picturestr.h" +#else +#include "picture.h" +#endif + +/* + * This single define controls the basic size of data manipulated + * by this software; it must be log2(sizeof (FbBits) * 8) + */ + +#ifndef FB_SHIFT +#define FB_SHIFT LOG2_BITMAP_PAD +#endif + +#if FB_SHIFT < LOG2_BITMAP_PAD + error FB_SHIFT must be >= LOG2_BITMAP_PAD +#endif + +#define FB_UNIT (1 << FB_SHIFT) +#define FB_HALFUNIT (1 << (FB_SHIFT-1)) +#define FB_MASK (FB_UNIT - 1) +#define FB_ALLONES ((FbBits) -1) + +#if GLYPHPADBYTES != 4 +#error "GLYPHPADBYTES must be 4" +#endif +#if GETLEFTBITS_ALIGNMENT != 1 +#error "GETLEFTBITS_ALIGNMENT must be 1" +#endif +/* whether to bother to include 24bpp support */ +#ifndef FBNO24BIT +#define FB_24BIT +#endif + +/* + * Unless otherwise instructed, fb includes code to advertise 24bpp + * windows with 32bpp image format for application compatibility + */ + +#ifdef FB_24BIT +#ifndef FBNO24_32 +#define FB_24_32BIT +#endif +#endif + +#define FB_STIP_SHIFT LOG2_BITMAP_PAD +#define FB_STIP_UNIT (1 << FB_STIP_SHIFT) +#define FB_STIP_MASK (FB_STIP_UNIT - 1) +#define FB_STIP_ALLONES ((FbStip) -1) + +#define FB_STIP_ODDSTRIDE(s) (((s) & (FB_MASK >> FB_STIP_SHIFT)) != 0) +#define FB_STIP_ODDPTR(p) ((((long) (p)) & (FB_MASK >> 3)) != 0) + +#define FbStipStrideToBitsStride(s) (((s) >> (FB_SHIFT - FB_STIP_SHIFT))) +#define FbBitsStrideToStipStride(s) (((s) << (FB_SHIFT - FB_STIP_SHIFT))) + +#define FbFullMask(n) ((n) == FB_UNIT ? FB_ALLONES : ((((FbBits) 1) << n) - 1)) + +#if FB_SHIFT == 6 +# ifdef WIN32 +typedef unsigned __int64 FbBits; +# else +# if defined(__alpha__) || defined(__alpha) || \ + defined(ia64) || defined(__ia64__) || \ + defined(__sparc64__) || \ + defined(__s390x__) || \ + defined(x86_64) || defined (__x86_64__) +typedef unsigned long FbBits; +# else +typedef unsigned long long FbBits; +# endif +# endif +#endif + +#if FB_SHIFT == 5 +typedef CARD32 FbBits; +#endif + +#if FB_SHIFT == 4 +typedef CARD16 FbBits; +#endif + +#if LOG2_BITMAP_PAD == FB_SHIFT +typedef FbBits FbStip; +#else +# if LOG2_BITMAP_PAD == 5 +typedef CARD32 FbStip; +# endif +#endif + +typedef int FbStride; + + +#ifdef FB_DEBUG +extern void fbValidateDrawable(DrawablePtr d); +extern void fbInitializeDrawable(DrawablePtr d); +extern void fbSetBits (FbStip *bits, int stride, FbStip data); +#define FB_HEAD_BITS (FbStip) (0xbaadf00d) +#define FB_TAIL_BITS (FbStip) (0xbaddf0ad) +#else +#define fbValidateDrawable(d) +#define fdInitializeDrawable(d) +#endif + +#include "fbrop.h" + +#if BITMAP_BIT_ORDER == LSBFirst +#define FbScrLeft(x,n) ((x) >> (n)) +#define FbScrRight(x,n) ((x) << (n)) +/* #define FbLeftBits(x,n) ((x) & ((((FbBits) 1) << (n)) - 1)) */ +#define FbLeftStipBits(x,n) ((x) & ((((FbStip) 1) << (n)) - 1)) +#define FbStipMoveLsb(x,s,n) (FbStipRight (x,(s)-(n))) +#define FbPatternOffsetBits 0 +#else +#define FbScrLeft(x,n) ((x) << (n)) +#define FbScrRight(x,n) ((x) >> (n)) +/* #define FbLeftBits(x,n) ((x) >> (FB_UNIT - (n))) */ +#define FbLeftStipBits(x,n) ((x) >> (FB_STIP_UNIT - (n))) +#define FbStipMoveLsb(x,s,n) (x) +#define FbPatternOffsetBits (sizeof (FbBits) - 1) +#endif + +#include "micoord.h" + +#define FbStipLeft(x,n) FbScrLeft(x,n) +#define FbStipRight(x,n) FbScrRight(x,n) + +#define FbRotLeft(x,n) FbScrLeft(x,n) | (n ? FbScrRight(x,FB_UNIT-n) : 0) +#define FbRotRight(x,n) FbScrRight(x,n) | (n ? FbScrLeft(x,FB_UNIT-n) : 0) + +#define FbRotStipLeft(x,n) FbStipLeft(x,n) | (n ? FbStipRight(x,FB_STIP_UNIT-n) : 0) +#define FbRotStipRight(x,n) FbStipRight(x,n) | (n ? FbStipLeft(x,FB_STIP_UNIT-n) : 0) + +#define FbLeftMask(x) ( ((x) & FB_MASK) ? \ + FbScrRight(FB_ALLONES,(x) & FB_MASK) : 0) +#define FbRightMask(x) ( ((FB_UNIT - (x)) & FB_MASK) ? \ + FbScrLeft(FB_ALLONES,(FB_UNIT - (x)) & FB_MASK) : 0) + +#define FbLeftStipMask(x) ( ((x) & FB_STIP_MASK) ? \ + FbStipRight(FB_STIP_ALLONES,(x) & FB_STIP_MASK) : 0) +#define FbRightStipMask(x) ( ((FB_STIP_UNIT - (x)) & FB_STIP_MASK) ? \ + FbScrLeft(FB_STIP_ALLONES,(FB_STIP_UNIT - (x)) & FB_STIP_MASK) : 0) + +#define FbBitsMask(x,w) (FbScrRight(FB_ALLONES,(x) & FB_MASK) & \ + FbScrLeft(FB_ALLONES,(FB_UNIT - ((x) + (w))) & FB_MASK)) + +#define FbStipMask(x,w) (FbStipRight(FB_STIP_ALLONES,(x) & FB_STIP_MASK) & \ + FbStipLeft(FB_STIP_ALLONES,(FB_STIP_UNIT - ((x)+(w))) & FB_STIP_MASK)) + + +#define FbMaskBits(x,w,l,n,r) { \ + n = (w); \ + r = FbRightMask((x)+n); \ + l = FbLeftMask(x); \ + if (l) { \ + n -= FB_UNIT - ((x) & FB_MASK); \ + if (n < 0) { \ + n = 0; \ + l &= r; \ + r = 0; \ + } \ + } \ + n >>= FB_SHIFT; \ +} + +#ifdef FBNOPIXADDR +#define FbMaskBitsBytes(x,w,copy,l,lb,n,r,rb) FbMaskBits(x,w,l,n,r) +#define FbDoLeftMaskByteRRop(dst,lb,l,and,xor) { \ + *dst = FbDoMaskRRop(*dst,and,xor,l); \ +} +#define FbDoRightMaskByteRRop(dst,rb,r,and,xor) { \ + *dst = FbDoMaskRRop(*dst,and,xor,r); \ +} +#else + +#define FbByteMaskInvalid 0x10 + +#define FbPatternOffset(o,t) ((o) ^ (FbPatternOffsetBits & ~(sizeof (t) - 1))) + +#define FbPtrOffset(p,o,t) ((t *) ((CARD8 *) (p) + (o))) +#define FbSelectPatternPart(xor,o,t) ((xor) >> (FbPatternOffset (o,t) << 3)) +#define FbStorePart(dst,off,t,xor) (*FbPtrOffset(dst,off,t) = \ + FbSelectPart(xor,off,t)) +#ifndef FbSelectPart +#define FbSelectPart(x,o,t) FbSelectPatternPart(x,o,t) +#endif + +#define FbMaskBitsBytes(x,w,copy,l,lb,n,r,rb) { \ + n = (w); \ + lb = 0; \ + rb = 0; \ + r = FbRightMask((x)+n); \ + if (r) { \ + /* compute right byte length */ \ + if ((copy) && (((x) + n) & 7) == 0) { \ + rb = (((x) + n) & FB_MASK) >> 3; \ + } else { \ + rb = FbByteMaskInvalid; \ + } \ + } \ + l = FbLeftMask(x); \ + if (l) { \ + /* compute left byte length */ \ + if ((copy) && ((x) & 7) == 0) { \ + lb = ((x) & FB_MASK) >> 3; \ + } else { \ + lb = FbByteMaskInvalid; \ + } \ + /* subtract out the portion painted by leftMask */ \ + n -= FB_UNIT - ((x) & FB_MASK); \ + if (n < 0) { \ + if (lb != FbByteMaskInvalid) { \ + if (rb == FbByteMaskInvalid) { \ + lb = FbByteMaskInvalid; \ + } else if (rb) { \ + lb |= (rb - lb) << (FB_SHIFT - 3); \ + rb = 0; \ + } \ + } \ + n = 0; \ + l &= r; \ + r = 0; \ + }\ + } \ + n >>= FB_SHIFT; \ +} + +#if FB_SHIFT == 6 +#define FbDoLeftMaskByteRRop6Cases(dst,xor) \ + case (sizeof (FbBits) - 7) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 7) | (2 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 7) | (3 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 7) | (4 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 7) | (5 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 7) | (6 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 7): \ + FbStorePart(dst,sizeof (FbBits) - 7,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD32,xor); \ + break; \ + case (sizeof (FbBits) - 6) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 6) | (2 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 6) | (3 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 6) | (4 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 6) | (5 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 6): \ + FbStorePart(dst,sizeof (FbBits) - 6,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD32,xor); \ + break; \ + case (sizeof (FbBits) - 5) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 5,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 5) | (2 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 5,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 5) | (3 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 5,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 5) | (4 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 5,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 5): \ + FbStorePart(dst,sizeof (FbBits) - 5,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD32,xor); \ + break; \ + case (sizeof (FbBits) - 4) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 4) | (2 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + break; \ + case (sizeof (FbBits) - 4) | (3 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD16,xor); \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 4): \ + FbStorePart(dst,sizeof (FbBits) - 4,CARD32,xor); \ + break; + +#define FbDoRightMaskByteRRop6Cases(dst,xor) \ + case 4: \ + FbStorePart(dst,0,CARD32,xor); \ + break; \ + case 5: \ + FbStorePart(dst,0,CARD32,xor); \ + FbStorePart(dst,4,CARD8,xor); \ + break; \ + case 6: \ + FbStorePart(dst,0,CARD32,xor); \ + FbStorePart(dst,4,CARD16,xor); \ + break; \ + case 7: \ + FbStorePart(dst,0,CARD32,xor); \ + FbStorePart(dst,4,CARD16,xor); \ + FbStorePart(dst,6,CARD8,xor); \ + break; +#else +#define FbDoLeftMaskByteRRop6Cases(dst,xor) +#define FbDoRightMaskByteRRop6Cases(dst,xor) +#endif + +#define FbDoLeftMaskByteRRop(dst,lb,l,and,xor) { \ + switch (lb) { \ + FbDoLeftMaskByteRRop6Cases(dst,xor) \ + case (sizeof (FbBits) - 3) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 3) | (2 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case (sizeof (FbBits) - 2) | (1 << (FB_SHIFT - 3)): \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD8,xor); \ + break; \ + case sizeof (FbBits) - 3: \ + FbStorePart(dst,sizeof (FbBits) - 3,CARD8,xor); \ + case sizeof (FbBits) - 2: \ + FbStorePart(dst,sizeof (FbBits) - 2,CARD16,xor); \ + break; \ + case sizeof (FbBits) - 1: \ + FbStorePart(dst,sizeof (FbBits) - 1,CARD8,xor); \ + break; \ + default: \ + *dst = FbDoMaskRRop(*dst, and, xor, l); \ + break; \ + } \ +} + + +#define FbDoRightMaskByteRRop(dst,rb,r,and,xor) { \ + switch (rb) { \ + case 1: \ + FbStorePart(dst,0,CARD8,xor); \ + break; \ + case 2: \ + FbStorePart(dst,0,CARD16,xor); \ + break; \ + case 3: \ + FbStorePart(dst,0,CARD16,xor); \ + FbStorePart(dst,2,CARD8,xor); \ + break; \ + FbDoRightMaskByteRRop6Cases(dst,xor) \ + default: \ + *dst = FbDoMaskRRop (*dst, and, xor, r); \ + } \ +} +#endif + +#define FbMaskStip(x,w,l,n,r) { \ + n = (w); \ + r = FbRightStipMask((x)+n); \ + l = FbLeftStipMask(x); \ + if (l) { \ + n -= FB_STIP_UNIT - ((x) & FB_STIP_MASK); \ + if (n < 0) { \ + n = 0; \ + l &= r; \ + r = 0; \ + } \ + } \ + n >>= FB_STIP_SHIFT; \ +} + +/* + * These macros are used to transparently stipple + * in copy mode; the expected usage is with 'n' constant + * so all of the conditional parts collapse into a minimal + * sequence of partial word writes + * + * 'n' is the bytemask of which bytes to store, 'a' is the address + * of the FbBits base unit, 'o' is the offset within that unit + * + * The term "lane" comes from the hardware term "byte-lane" which + */ + +#define FbLaneCase1(n,a,o) ((n) == 0x01 ? \ + (*(CARD8 *) ((a)+FbPatternOffset(o,CARD8)) = \ + fgxor) : 0) +#define FbLaneCase2(n,a,o) ((n) == 0x03 ? \ + (*(CARD16 *) ((a)+FbPatternOffset(o,CARD16)) = \ + fgxor) : \ + ((void)FbLaneCase1((n)&1,a,o), \ + FbLaneCase1((n)>>1,a,(o)+1))) +#define FbLaneCase4(n,a,o) ((n) == 0x0f ? \ + (*(CARD32 *) ((a)+FbPatternOffset(o,CARD32)) = \ + fgxor) : \ + ((void)FbLaneCase2((n)&3,a,o), \ + FbLaneCase2((n)>>2,a,(o)+2))) +#define FbLaneCase8(n,a,o) ((n) == 0x0ff ? (*(FbBits *) ((a)+(o)) = fgxor) : \ + ((void)FbLaneCase4((n)&15,a,o), \ + FbLaneCase4((n)>>4,a,(o)+4))) + +#if FB_SHIFT == 6 +#define FbLaneCase(n,a) FbLaneCase8(n,(CARD8 *) (a),0) +#endif + +#if FB_SHIFT == 5 +#define FbLaneCase(n,a) FbLaneCase4(n,(CARD8 *) (a),0) +#endif + +/* Rotate a filled pixel value to the specified alignement */ +#define FbRot24(p,b) (FbScrRight(p,b) | FbScrLeft(p,24-(b))) +#define FbRot24Stip(p,b) (FbStipRight(p,b) | FbStipLeft(p,24-(b))) + +/* step a filled pixel value to the next/previous FB_UNIT alignment */ +#define FbNext24Pix(p) (FbRot24(p,(24-FB_UNIT%24))) +#define FbPrev24Pix(p) (FbRot24(p,FB_UNIT%24)) +#define FbNext24Stip(p) (FbRot24(p,(24-FB_STIP_UNIT%24))) +#define FbPrev24Stip(p) (FbRot24(p,FB_STIP_UNIT%24)) + +/* step a rotation value to the next/previous rotation value */ +#if FB_UNIT == 64 +#define FbNext24Rot(r) ((r) == 16 ? 0 : (r) + 8) +#define FbPrev24Rot(r) ((r) == 0 ? 16 : (r) - 8) + +#if IMAGE_BYTE_ORDER == MSBFirst +#define FbFirst24Rot(x) (((x) + 8) % 24) +#else +#define FbFirst24Rot(x) ((x) % 24) +#endif + +#endif + +#if FB_UNIT == 32 +#define FbNext24Rot(r) ((r) == 0 ? 16 : (r) - 8) +#define FbPrev24Rot(r) ((r) == 16 ? 0 : (r) + 8) + +#if IMAGE_BYTE_ORDER == MSBFirst +#define FbFirst24Rot(x) (((x) + 16) % 24) +#else +#define FbFirst24Rot(x) ((x) % 24) +#endif +#endif + +#define FbNext24RotStip(r) ((r) == 0 ? 16 : (r) - 8) +#define FbPrev24RotStip(r) ((r) == 16 ? 0 : (r) + 8) + +/* Whether 24-bit specific code is needed for this filled pixel value */ +#define FbCheck24Pix(p) ((p) == FbNext24Pix(p)) + +/* Macros for dealing with dashing */ + +#define FbDashDeclare \ + unsigned char *__dash, *__firstDash, *__lastDash + +#define FbDashInit(pGC,pPriv,dashOffset,dashlen,even) { \ + (even) = TRUE; \ + __firstDash = (pGC)->dash; \ + __lastDash = __firstDash + (pGC)->numInDashList; \ + (dashOffset) %= (pPriv)->dashLength; \ + \ + __dash = __firstDash; \ + while ((dashOffset) >= ((dashlen) = *__dash)) \ + { \ + (dashOffset) -= (dashlen); \ + (even) = 1-(even); \ + if (++__dash == __lastDash) \ + __dash = __firstDash; \ + } \ + (dashlen) -= (dashOffset); \ +} + +#define FbDashNext(dashlen) { \ + if (++__dash == __lastDash) \ + __dash = __firstDash; \ + (dashlen) = *__dash; \ +} + +/* as numInDashList is always even, this case can skip a test */ + +#define FbDashNextEven(dashlen) { \ + (dashlen) = *++__dash; \ +} + +#define FbDashNextOdd(dashlen) FbDashNext(dashlen) + +#define FbDashStep(dashlen,even) { \ + if (!--(dashlen)) { \ + FbDashNext(dashlen); \ + (even) = 1-(even); \ + } \ +} + +extern int fbGCPrivateIndex; +#ifndef FB_NO_WINDOW_PIXMAPS +extern int fbWinPrivateIndex; +#endif +extern const GCOps fbGCOps; +extern const GCFuncs fbGCFuncs; + +#ifdef TEKX11 +#define FB_OLD_GC +#define FB_OLD_SCREEN +#endif + +#ifdef FB_OLD_SCREEN +extern WindowPtr *WindowTable; +#endif + +#ifdef FB_24_32BIT +#define FB_SCREEN_PRIVATE +#endif + +#ifdef FB_SCREEN_PRIVATE +extern int fbScreenPrivateIndex; + +/* private field of a screen */ +typedef struct { + unsigned char win32bpp; /* window bpp for 32-bpp images */ + unsigned char pix32bpp; /* pixmap bpp for 32-bpp images */ +} FbScreenPrivRec, *FbScreenPrivPtr; + +#define fbGetScreenPrivate(pScreen) ((FbScreenPrivPtr) \ + (pScreen)->devPrivates[fbScreenPrivateIndex].ptr) +#endif + +/* private field of GC */ +typedef struct { +#ifdef FB_OLD_GC + unsigned char pad1; + unsigned char pad2; + unsigned char pad3; + unsigned fExpose:1; + unsigned freeCompClip:1; + PixmapPtr pRotatedPixmap; + RegionPtr pCompositeClip; +#endif + FbBits and, xor; /* reduced rop values */ + FbBits bgand, bgxor; /* for stipples */ + FbBits fg, bg, pm; /* expanded and filled */ + unsigned int dashLength; /* total of all dash elements */ + unsigned char oneRect; /* clip list is single rectangle */ + unsigned char evenStipple; /* stipple is even */ + unsigned char bpp; /* current drawable bpp */ +} FbGCPrivRec, *FbGCPrivPtr; + +#define fbGetGCPrivate(pGC) ((FbGCPrivPtr)\ + (pGC)->devPrivates[fbGCPrivateIndex].ptr) + +#ifdef FB_OLD_GC +#define fbGetCompositeClip(pGC) (fbGetGCPrivate(pGC)->pCompositeClip) +#define fbGetExpose(pGC) (fbGetGCPrivate(pGC)->fExpose) +#define fbGetFreeCompClip(pGC) (fbGetGCPrivate(pGC)->freeCompClip) +#define fbGetRotatedPixmap(pGC) (fbGetGCPrivate(pGC)->pRotatedPixmap) +#else +#define fbGetCompositeClip(pGC) ((pGC)->pCompositeClip) +#define fbGetExpose(pGC) ((pGC)->fExpose) +#define fbGetFreeCompClip(pGC) ((pGC)->freeCompClip) +#define fbGetRotatedPixmap(pGC) ((pGC)->pRotatedPixmap) +#endif + +#define fbGetScreenPixmap(s) ((PixmapPtr) (s)->devPrivate) +#ifdef FB_NO_WINDOW_PIXMAPS +#define fbGetWindowPixmap(d) fbGetScreenPixmap(((DrawablePtr) (d))->pScreen) +#else +#define fbGetWindowPixmap(pWin) ((PixmapPtr)\ + ((WindowPtr) (pWin))->devPrivates[fbWinPrivateIndex].ptr) +#endif + +#ifdef __DARWIN__ +#define __fbPixOriginX(pPix) ((pPix)->drawable.x) +#define __fbPixOriginY(pPix) ((pPix)->drawable.y) +#else +#define __fbPixOriginX(pPix) 0 +#define __fbPixOriginY(pPix) 0 +#endif + +#define fbGetDrawable(pDrawable, pointer, stride, bpp, xoff, yoff) { \ + PixmapPtr _pPix; \ + if ((pDrawable)->type != DRAWABLE_PIXMAP) \ + _pPix = fbGetWindowPixmap(pDrawable); \ + else \ + _pPix = (PixmapPtr) (pDrawable); \ + (pointer) = (FbBits *) _pPix->devPrivate.ptr; \ + (stride) = ((int) _pPix->devKind) / sizeof (FbBits); \ + (bpp) = _pPix->drawable.bitsPerPixel; \ + (xoff) = __fbPixOriginX(_pPix); \ + (yoff) = __fbPixOriginY(_pPix); \ +} + +#define fbGetStipDrawable(pDrawable, pointer, stride, bpp, xoff, yoff) { \ + PixmapPtr _pPix; \ + if ((pDrawable)->type != DRAWABLE_PIXMAP) \ + _pPix = fbGetWindowPixmap(pDrawable); \ + else \ + _pPix = (PixmapPtr) (pDrawable); \ + (pointer) = (FbStip *) _pPix->devPrivate.ptr; \ + (stride) = ((int) _pPix->devKind) / sizeof (FbStip); \ + (bpp) = _pPix->drawable.bitsPerPixel; \ + (xoff) = __fbPixOriginX(_pPix); \ + (yoff) = __fbPixOriginY(_pPix); \ +} + +/* + * XFree86 empties the root BorderClip when the VT is inactive, + * here's a macro which uses that to disable GetImage and GetSpans + */ + +#define fbWindowEnabled(pWin) \ + REGION_NOTEMPTY((pWin)->drawable.pScreen, \ + &WindowTable[(pWin)->drawable.pScreen->myNum]->borderClip) + +#define fbDrawableEnabled(pDrawable) \ + ((pDrawable)->type == DRAWABLE_PIXMAP ? \ + TRUE : fbWindowEnabled((WindowPtr) pDrawable)) + +#ifdef FB_OLD_SCREEN +#define BitsPerPixel(d) (\ + ((1 << PixmapWidthPaddingInfo[d].padBytesLog2) * 8 / \ + (PixmapWidthPaddingInfo[d].padRoundUp+1))) +#endif + +#define FbPowerOfTwo(w) (((w) & ((w) - 1)) == 0) +/* + * Accelerated tiles are power of 2 width <= FB_UNIT + */ +#define FbEvenTile(w) ((w) <= FB_UNIT && FbPowerOfTwo(w)) +/* + * Accelerated stipples are power of 2 width and <= FB_UNIT/dstBpp + * with dstBpp a power of 2 as well + */ +#define FbEvenStip(w,bpp) ((w) * (bpp) <= FB_UNIT && FbPowerOfTwo(w) && FbPowerOfTwo(bpp)) + +/* + * fb24_32.c + */ +void +fb24_32GetSpans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, + int *pwidth, + int nspans, + char *pchardstStart); + +void +fb24_32SetSpans (DrawablePtr pDrawable, + GCPtr pGC, + char *src, + DDXPointPtr ppt, + int *pwidth, + int nspans, + int fSorted); + +void +fb24_32PutZImage (DrawablePtr pDrawable, + RegionPtr pClip, + int alu, + FbBits pm, + int x, + int y, + int width, + int height, + CARD8 *src, + FbStride srcStride); + +void +fb24_32GetImage (DrawablePtr pDrawable, + int x, + int y, + int w, + int h, + unsigned int format, + unsigned long planeMask, + char *d); + +void +fb24_32CopyMtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure); + +PixmapPtr +fb24_32ReformatTile(PixmapPtr pOldTile, int bitsPerPixel); + +Bool +fb24_32CreateScreenResources(ScreenPtr pScreen); + +Bool +fb24_32ModifyPixmapHeader (PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, + int devKind, + pointer pPixData); + +/* + * fballpriv.c + */ +Bool +fbAllocatePrivates(ScreenPtr pScreen, int *pGCIndex); + +/* + * fbarc.c + */ + +void +fbPolyArc (DrawablePtr pDrawable, + GCPtr pGC, + int narcs, + xArc *parcs); + +/* + * fbbits.c + */ + +void +fbBresSolid8(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x, + int y, + int e, + int e1, + int e3, + int len); + +void +fbBresDash8 (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x, + int y, + int e, + int e1, + int e3, + int len); + +void +fbDots8 (FbBits *dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint *pts, + int npt, + int xoff, + int yoff, + FbBits and, + FbBits xor); + +void +fbArc8 (FbBits *dst, + FbStride dstStride, + int dstBpp, + xArc *arc, + int dx, + int dy, + FbBits and, + FbBits xor); + +void +fbGlyph8 (FbBits *dstLine, + FbStride dstStride, + int dstBpp, + FbStip *stipple, + FbBits fg, + int height, + int shift); + +void +fbPolyline8 (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ptsOrig); + +void +fbPolySegment8 (DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pseg); + +void +fbBresSolid16(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x, + int y, + int e, + int e1, + int e3, + int len); + +void +fbBresDash16(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x, + int y, + int e, + int e1, + int e3, + int len); + +void +fbDots16(FbBits *dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint *pts, + int npt, + int xoff, + int yoff, + FbBits and, + FbBits xor); + +void +fbArc16(FbBits *dst, + FbStride dstStride, + int dstBpp, + xArc *arc, + int dx, + int dy, + FbBits and, + FbBits xor); + +void +fbGlyph16(FbBits *dstLine, + FbStride dstStride, + int dstBpp, + FbStip *stipple, + FbBits fg, + int height, + int shift); + +void +fbPolyline16 (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ptsOrig); + +void +fbPolySegment16 (DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pseg); + + +void +fbBresSolid24(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x, + int y, + int e, + int e1, + int e3, + int len); + +void +fbBresDash24(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x, + int y, + int e, + int e1, + int e3, + int len); + +void +fbDots24(FbBits *dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint *pts, + int npt, + int xoff, + int yoff, + FbBits and, + FbBits xor); + +void +fbArc24(FbBits *dst, + FbStride dstStride, + int dstBpp, + xArc *arc, + int dx, + int dy, + FbBits and, + FbBits xor); + +void +fbGlyph24(FbBits *dstLine, + FbStride dstStride, + int dstBpp, + FbStip *stipple, + FbBits fg, + int height, + int shift); + +void +fbPolyline24 (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ptsOrig); + +void +fbPolySegment24 (DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pseg); + + +void +fbBresSolid32(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x, + int y, + int e, + int e1, + int e3, + int len); + +void +fbBresDash32(DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x, + int y, + int e, + int e1, + int e3, + int len); + +void +fbDots32(FbBits *dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint *pts, + int npt, + int xoff, + int yoff, + FbBits and, + FbBits xor); + +void +fbArc32(FbBits *dst, + FbStride dstStride, + int dstBpp, + xArc *arc, + int dx, + int dy, + FbBits and, + FbBits xor); + +void +fbGlyph32(FbBits *dstLine, + FbStride dstStride, + int dstBpp, + FbStip *stipple, + FbBits fg, + int height, + int shift); +void +fbPolyline32 (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ptsOrig); + +void +fbPolySegment32 (DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pseg); + +/* + * fbblt.c + */ +void +fbBlt (FbBits *src, + FbStride srcStride, + int srcX, + + FbBits *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + int alu, + FbBits pm, + int bpp, + + Bool reverse, + Bool upsidedown); + +void +fbBlt24 (FbBits *srcLine, + FbStride srcStride, + int srcX, + + FbBits *dstLine, + FbStride dstStride, + int dstX, + + int width, + int height, + + int alu, + FbBits pm, + + Bool reverse, + Bool upsidedown); + +void +fbBltStip (FbStip *src, + FbStride srcStride, /* in FbStip units, not FbBits units */ + int srcX, + + FbStip *dst, + FbStride dstStride, /* in FbStip units, not FbBits units */ + int dstX, + + int width, + int height, + + int alu, + FbBits pm, + int bpp); + +/* + * fbbltone.c + */ +void +fbBltOne (FbStip *src, + FbStride srcStride, + int srcX, + FbBits *dst, + FbStride dstStride, + int dstX, + int dstBpp, + + int width, + int height, + + FbBits fgand, + FbBits fbxor, + FbBits bgand, + FbBits bgxor); + +#ifdef FB_24BIT +void +fbBltOne24 (FbStip *src, + FbStride srcStride, /* FbStip units per scanline */ + int srcX, /* bit position of source */ + FbBits *dst, + FbStride dstStride, /* FbBits units per scanline */ + int dstX, /* bit position of dest */ + int dstBpp, /* bits per destination unit */ + + int width, /* width in bits of destination */ + int height, /* height in scanlines */ + + FbBits fgand, /* rrop values */ + FbBits fgxor, + FbBits bgand, + FbBits bgxor); +#endif + +void +fbBltPlane (FbBits *src, + FbStride srcStride, + int srcX, + int srcBpp, + + FbStip *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + FbStip fgand, + FbStip fgxor, + FbStip bgand, + FbStip bgxor, + Pixel planeMask); + +/* + * fbbstore.c + */ +void +fbSaveAreas(PixmapPtr pPixmap, + RegionPtr prgnSave, + int xorg, + int yorg, + WindowPtr pWin); + +void +fbRestoreAreas(PixmapPtr pPixmap, + RegionPtr prgnRestore, + int xorg, + int yorg, + WindowPtr pWin); + +/* + * fbcmap.c + */ +int +fbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps); + +void +fbInstallColormap(ColormapPtr pmap); + +void +fbUninstallColormap(ColormapPtr pmap); + +void +fbResolveColor(unsigned short *pred, + unsigned short *pgreen, + unsigned short *pblue, + VisualPtr pVisual); + +Bool +fbInitializeColormap(ColormapPtr pmap); + +int +fbExpandDirectColors (ColormapPtr pmap, + int ndef, + xColorItem *indefs, + xColorItem *outdefs); + +Bool +fbCreateDefColormap(ScreenPtr pScreen); + +void +fbClearVisualTypes(void); + +Bool +fbSetVisualTypes (int depth, int visuals, int bitsPerRGB); + +Bool +fbSetVisualTypesAndMasks (int depth, int visuals, int bitsPerRGB, + Pixel redMask, Pixel greenMask, Pixel blueMask); + +Bool +fbInitVisuals (VisualPtr *visualp, + DepthPtr *depthp, + int *nvisualp, + int *ndepthp, + int *rootDepthp, + VisualID *defaultVisp, + unsigned long sizes, + int bitsPerRGB); + +/* + * fbcopy.c + */ + +typedef void (*fbCopyProc) (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pDstBox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure); + +void +fbCopyNtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure); + +void +fbCopy1toN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure); + +void +fbCopyNto1 (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure); + +void +fbCopyRegion (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + RegionPtr pDstRegion, + int dx, + int dy, + fbCopyProc copyProc, + Pixel bitPlane, + void *closure); + +RegionPtr +fbDoCopy (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, + int xOut, + int yOut, + fbCopyProc copyProc, + Pixel bitplane, + void *closure); + +RegionPtr +fbCopyArea (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, + int xOut, + int yOut); + +RegionPtr +fbCopyPlane (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, + int xOut, + int yOut, + unsigned long bitplane); + +/* + * fbfill.c + */ +void +fbFill (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int width, + int height); + +void +fbSolidBoxClipped (DrawablePtr pDrawable, + RegionPtr pClip, + int xa, + int ya, + int xb, + int yb, + FbBits and, + FbBits xor); + +/* + * fbfillrect.c + */ +void +fbPolyFillRect(DrawablePtr pDrawable, + GCPtr pGC, + int nrectInit, + xRectangle *prectInit); + +#define fbPolyFillArc miPolyFillArc + +#define fbFillPolygon miFillPolygon + +/* + * fbfillsp.c + */ +void +fbFillSpans (DrawablePtr pDrawable, + GCPtr pGC, + int nInit, + DDXPointPtr pptInit, + int *pwidthInit, + int fSorted); + + +/* + * fbgc.c + */ + +Bool +fbCreateGC(GCPtr pGC); + +void +fbPadPixmap (PixmapPtr pPixmap); + +void +fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable); + +/* + * fbgetsp.c + */ +void +fbGetSpans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, + int *pwidth, + int nspans, + char *pchardstStart); + +/* + * fbglyph.c + */ + +Bool +fbGlyphIn (RegionPtr pRegion, + int x, + int y, + int width, + int height); + +void +fbPolyGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase); + +void +fbImageGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase); + +/* + * fbimage.c + */ + +void +fbPutImage (DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage); + +void +fbPutZImage (DrawablePtr pDrawable, + RegionPtr pClip, + int alu, + FbBits pm, + int x, + int y, + int width, + int height, + FbStip *src, + FbStride srcStride); + +void +fbPutXYImage (DrawablePtr pDrawable, + RegionPtr pClip, + FbBits fg, + FbBits bg, + FbBits pm, + int alu, + Bool opaque, + + int x, + int y, + int width, + int height, + + FbStip *src, + FbStride srcStride, + int srcX); + +void +fbGetImage (DrawablePtr pDrawable, + int x, + int y, + int w, + int h, + unsigned int format, + unsigned long planeMask, + char *d); +/* + * fbline.c + */ + +void +fbZeroLine (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ppt); + +void +fbZeroSegment (DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pSegs); + +void +fbPolyLine (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ppt); + +void +fbFixCoordModePrevious (int npt, + DDXPointPtr ppt); + +void +fbPolySegment (DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pseg); + +#define fbPolyRectangle miPolyRectangle + +/* + * fbpict.c + */ + +Bool +fbPictureInit (ScreenPtr pScreen, + PictFormatPtr formats, + int nformats); + +/* + * fbpixmap.c + */ + +PixmapPtr +fbCreatePixmapBpp (ScreenPtr pScreen, int width, int height, int depth, int bpp); + +PixmapPtr +fbCreatePixmap (ScreenPtr pScreen, int width, int height, int depth); + +Bool +fbDestroyPixmap (PixmapPtr pPixmap); + +RegionPtr +fbPixmapToRegion(PixmapPtr pPix); + +/* + * fbpoint.c + */ + +void +fbDots (FbBits *dstOrig, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint *pts, + int npt, + int xoff, + int yoff, + FbBits andOrig, + FbBits xorOrig); + +void +fbPolyPoint (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + xPoint *pptInit); + +/* + * fbpush.c + */ +void +fbPushPattern (DrawablePtr pDrawable, + GCPtr pGC, + + FbStip *src, + FbStride srcStride, + int srcX, + + int x, + int y, + + int width, + int height); + +void +fbPushFill (DrawablePtr pDrawable, + GCPtr pGC, + + FbStip *src, + FbStride srcStride, + int srcX, + + int x, + int y, + int width, + int height); + +void +fbPush1toN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure); + +void +fbPushImage (DrawablePtr pDrawable, + GCPtr pGC, + + FbStip *src, + FbStride srcStride, + int srcX, + + int x, + int y, + int width, + int height); + +void +fbPushPixels (GCPtr pGC, + PixmapPtr pBitmap, + DrawablePtr pDrawable, + int dx, + int dy, + int xOrg, + int yOrg); + + +/* + * fbscreen.c + */ + +Bool +fbCloseScreen (int indx, ScreenPtr pScreen); + +Bool +fbRealizeFont(ScreenPtr pScreen, FontPtr pFont); + +Bool +fbUnrealizeFont(ScreenPtr pScreen, FontPtr pFont); + +void +fbQueryBestSize (int class, + unsigned short *width, unsigned short *height, + ScreenPtr pScreen); + +#ifndef FB_OLD_SCREEN +PixmapPtr +_fbGetWindowPixmap (WindowPtr pWindow); + +void +_fbSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap); +#endif + +Bool +fbSetupScreen(ScreenPtr pScreen, + pointer pbits, /* pointer to screen bitmap */ + int xsize, /* in pixels */ + int ysize, + int dpix, /* dots per inch */ + int dpiy, + int width, /* pixel width of frame buffer */ + int bpp); /* bits per pixel of frame buffer */ + +Bool +fbFinishScreenInit(ScreenPtr pScreen, + pointer pbits, + int xsize, + int ysize, + int dpix, + int dpiy, + int width, + int bpp); + +Bool +fbScreenInit(ScreenPtr pScreen, + pointer pbits, + int xsize, + int ysize, + int dpix, + int dpiy, + int width, + int bpp); + +void +fbInitializeBackingStore (ScreenPtr pScreen); + +/* + * fbseg.c + */ +typedef void FbBres (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x, + int y, + int e, + int e1, + int e3, + int len); + +FbBres fbBresSolid, fbBresDash, fbBresFill, fbBresFillDash; +/* + * fbsetsp.c + */ + +void +fbSetSpans (DrawablePtr pDrawable, + GCPtr pGC, + char *src, + DDXPointPtr ppt, + int *pwidth, + int nspans, + int fSorted); + +FbBres * +fbSelectBres (DrawablePtr pDrawable, + GCPtr pGC); + +void +fbBres (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x, + int y, + int e, + int e1, + int e3, + int len); + +void +fbSegment (DrawablePtr pDrawable, + GCPtr pGC, + int xa, + int ya, + int xb, + int yb, + Bool drawLast, + int *dashOffset); + + +/* + * fbsolid.c + */ + +void +fbSolid (FbBits *dst, + FbStride dstStride, + int dstX, + int bpp, + + int width, + int height, + + FbBits and, + FbBits xor); + +#ifdef FB_24BIT +void +fbSolid24 (FbBits *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + FbBits and, + FbBits xor); +#endif + +/* + * fbstipple.c + */ + +void +fbTransparentSpan (FbBits *dst, + FbBits stip, + FbBits fgxor, + int n); + +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); + +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); + +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); + +/* + * fbtile.c + */ + +void +fbEvenTile (FbBits *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + FbBits *tile, + int tileHeight, + + int alu, + FbBits pm, + int xRot, + int yRot); + +void +fbOddTile (FbBits *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + FbBits *tile, + FbStride tileStride, + int tileWidth, + int tileHeight, + + int alu, + FbBits pm, + int bpp, + + int xRot, + int yRot); + +void +fbTile (FbBits *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + FbBits *tile, + FbStride tileStride, + int tileWidth, + int tileHeight, + + int alu, + FbBits pm, + int bpp, + + int xRot, + int yRot); + +/* + * fbutil.c + */ +FbBits +fbReplicatePixel (Pixel p, int bpp); + +void +fbReduceRasterOp (int rop, FbBits fg, FbBits pm, FbBits *andp, FbBits *xorp); + +/* + * fbwindow.c + */ + +Bool +fbCreateWindow(WindowPtr pWin); + +Bool +fbDestroyWindow(WindowPtr pWin); + +Bool +fbMapWindow(WindowPtr pWindow); + +Bool +fbPositionWindow(WindowPtr pWin, int x, int y); + +Bool +fbUnmapWindow(WindowPtr pWindow); + +void +fbCopyWindowProc (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure); + +void +fbCopyWindow(WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc); + +Bool +fbChangeWindowAttributes(WindowPtr pWin, unsigned long mask); + +void +fbFillRegionSolid (DrawablePtr pDrawable, + RegionPtr pRegion, + FbBits and, + FbBits xor); + +void +fbFillRegionTiled (DrawablePtr pDrawable, + RegionPtr pRegion, + PixmapPtr pTile); + +void +fbPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); + + +#endif /* _FB_H_ */ diff --git a/fb/fb24_32.c b/fb/fb24_32.c new file mode 100644 index 000000000..1f9e843cf --- /dev/null +++ b/fb/fb24_32.c @@ -0,0 +1,623 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fb24_32.c,v 1.5 2001/05/29 04:54:08 keithp Exp $ + * + * Copyright © 2000 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. + */ + +#ifdef XFree86LOADER +#include "xf86.h" +#include "xf86_ansic.h" +#endif + +#include "fb.h" + +/* X apps don't like 24bpp images, this code exposes 32bpp images */ + +/* + * These two functions do a full CopyArea while reformatting + * the data between 24 and 32bpp. They try to go a bit faster + * by reading/writing aligned CARD32s where it's easy + */ + +#define Get8(a) ((CARD32) *(a)) + +#if BITMAP_BIT_ORDER == MSBFirst +#define Get24(a) ((Get8(a) << 16) | (Get8((a)+1) << 8) | Get8((a)+2)) +#define Put24(a,p) (((a)[0] = (CARD8) ((p) >> 16)), \ + ((a)[1] = (CARD8) ((p) >> 8)), \ + ((a)[2] = (CARD8) (p))) +#else +#define Get24(a) (Get8(a) | (Get8((a)+1) << 8) | (Get8((a)+2)<<16)) +#define Put24(a,p) (((a)[0] = (CARD8) (p)), \ + ((a)[1] = (CARD8) ((p) >> 8)), \ + ((a)[2] = (CARD8) ((p) >> 16))) +#endif + +typedef void (*fb24_32BltFunc) (CARD8 *srcLine, + FbStride srcStride, + int srcX, + + CARD8 *dstLine, + FbStride dstStride, + int dstX, + + int width, + int height, + + int alu, + FbBits pm); + +static void +fb24_32BltDown (CARD8 *srcLine, + FbStride srcStride, + int srcX, + + CARD8 *dstLine, + FbStride dstStride, + int dstX, + + int width, + int height, + + int alu, + FbBits pm) +{ + CARD32 *src; + CARD8 *dst; + int w; + Bool destInvarient; + CARD32 pixel, dpixel; + FbDeclareMergeRop (); + + srcLine += srcX * 4; + dstLine += dstX * 3; + + FbInitializeMergeRop(alu, (pm | ~(FbBits) 0xffffff)); + destInvarient = FbDestInvarientMergeRop(); + + while (height--) + { + src = (CARD32 *) srcLine; + dst = dstLine; + srcLine += srcStride; + dstLine += dstStride; + w = width; + if (destInvarient) + { + while (((long) dst & 3) && w) + { + w--; + pixel = *src++; + pixel = FbDoDestInvarientMergeRop(pixel); + Put24 (dst, pixel); + dst += 3; + } + /* Do four aligned pixels at a time */ + while (w >= 4) + { + CARD32 s0, s1; + s0 = *src++; + s0 = FbDoDestInvarientMergeRop(s0); + s1 = *src++; + s1 = FbDoDestInvarientMergeRop(s1); +#if BITMAP_BIT_ORDER == LSBFirst + *(CARD32 *)(dst) = (s0 & 0xffffff) | (s1 << 24); +#else + *(CARD32 *)(dst) = (s0 << 8) | ((s1 & 0xffffff) >> 16); +#endif + s0 = *src++; + s0 = FbDoDestInvarientMergeRop(s0); +#if BITMAP_BIT_ORDER == LSBFirst + *(CARD32 *)(dst+4) = ((s1 & 0xffffff) >> 8) | (s0 << 16); +#else + *(CARD32 *)(dst+4) = (s1 << 16) | ((s0 & 0xffffff) >> 8); +#endif + s1 = *src++; + s1 = FbDoDestInvarientMergeRop(s1); +#if BITMAP_BIT_ORDER == LSBFirst + *(CARD32 *)(dst+8) = ((s0 & 0xffffff) >> 16) | (s1 << 8); +#else + *(CARD32 *)(dst+8) = (s0 << 24) | (s1 & 0xffffff); +#endif + dst += 12; + w -= 4; + } + while (w--) + { + pixel = *src++; + pixel = FbDoDestInvarientMergeRop(pixel); + Put24 (dst, pixel); + dst += 3; + } + } + else + { + while (w--) + { + pixel = *src++; + dpixel = Get24 (dst); + pixel = FbDoMergeRop(pixel, dpixel); + Put24 (dst, pixel); + dst += 3; + } + } + } +} + +static void +fb24_32BltUp (CARD8 *srcLine, + FbStride srcStride, + int srcX, + + CARD8 *dstLine, + FbStride dstStride, + int dstX, + + int width, + int height, + + int alu, + FbBits pm) +{ + CARD8 *src; + CARD32 *dst; + int w; + Bool destInvarient; + CARD32 pixel; + FbDeclareMergeRop (); + + FbInitializeMergeRop(alu, (pm | (~(FbBits) 0xffffff))); + destInvarient = FbDestInvarientMergeRop(); + + srcLine += srcX * 3; + dstLine += dstX * 4; + + while (height--) + { + w = width; + src = srcLine; + dst = (CARD32 *) dstLine; + srcLine += srcStride; + dstLine += dstStride; + if (destInvarient) + { + while (((long) src & 3) && w) + { + w--; + pixel = Get24(src); + src += 3; + *dst++ = FbDoDestInvarientMergeRop(pixel); + } + /* Do four aligned pixels at a time */ + while (w >= 4) + { + CARD32 s0, s1; + + s0 = *(CARD32 *)(src); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = s0 & 0xffffff; +#else + pixel = s0 >> 8; +#endif + *dst++ = FbDoDestInvarientMergeRop(pixel); + s1 = *(CARD32 *)(src+4); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = (s0 >> 24) | ((s1 << 8) & 0xffffff); +#else + pixel = ((s0 << 16) & 0xffffff) | (s1 >> 16); +#endif + *dst++ = FbDoDestInvarientMergeRop(pixel); + s0 = *(CARD32 *)(src+8); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = (s1 >> 16) | ((s0 << 16) & 0xffffff); +#else + pixel = ((s1 << 8) & 0xffffff) | (s0 >> 24); +#endif + *dst++ = FbDoDestInvarientMergeRop(pixel); +#if BITMAP_BIT_ORDER == LSBFirst + pixel = s0 >> 8; +#else + pixel = s0 & 0xffffff; +#endif + *dst++ = FbDoDestInvarientMergeRop(pixel); + src += 12; + w -= 4; + } + while (w) + { + w--; + pixel = Get24(src); + src += 3; + *dst++ = FbDoDestInvarientMergeRop(pixel); + } + } + else + { + while (w--) + { + pixel = Get24(src); + src += 3; + *dst = FbDoMergeRop(pixel, *dst); + dst++; + } + } + } +} + +/* + * Spans functions; probably unused. + */ +void +fb24_32GetSpans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, + int *pwidth, + int nspans, + char *pchardstStart) +{ + FbBits *srcBits; + CARD8 *src; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + CARD8 *dst; + + fbGetDrawable (pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); + src = (CARD8 *) srcBits; + srcStride *= sizeof (FbBits); + + while (nspans--) + { + dst = (CARD8 *) pchardstStart; + fb24_32BltUp (src + (ppt->y + srcYoff) * srcStride, srcStride, + ppt->x + srcXoff, + + dst, + 1, + 0, + + *pwidth, + 1, + + GXcopy, + FB_ALLONES); + + pchardstStart += PixmapBytePad(*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } +} + +void +fb24_32SetSpans (DrawablePtr pDrawable, + GCPtr pGC, + char *src, + DDXPointPtr ppt, + int *pwidth, + int nspans, + int fSorted) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + RegionPtr pClip = fbGetCompositeClip(pGC); + FbBits *dstBits; + CARD8 *dst, *d, *s; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + BoxPtr pbox; + int n; + int x1, x2; + + fbGetDrawable (pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + dst = (CARD8 *) dstBits; + dstStride *= sizeof (FbBits); + while (nspans--) + { + d = dst + (ppt->y + dstYoff) * dstStride; + s = (CARD8 *) src; + n = REGION_NUM_RECTS(pClip); + pbox = REGION_RECTS (pClip); + while (n--) + { + if (pbox->y1 > ppt->y) + break; + if (pbox->y2 > ppt->y) + { + x1 = ppt->x; + x2 = x1 + *pwidth; + if (pbox->x1 > x1) + x1 = pbox->x1; + if (pbox->x2 < x2) + x2 = pbox->x2; + if (x1 < x2) + fb24_32BltDown (s, + 0, + (x1 - ppt->x), + d, + dstStride, + x1 + dstXoff, + + (x2 - x1), + 1, + pGC->alu, + pPriv->pm); + } + } + src += PixmapBytePad (*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } +} + +/* + * Clip and put 32bpp Z-format images to a 24bpp drawable + */ +void +fb24_32PutZImage (DrawablePtr pDrawable, + RegionPtr pClip, + int alu, + FbBits pm, + int x, + int y, + int width, + int height, + CARD8 *src, + FbStride srcStride) +{ + FbBits *dstBits; + CARD8 *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + int nbox; + BoxPtr pbox; + int x1, y1, x2, y2; + + fbGetDrawable (pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + dstStride *= sizeof(FbBits); + dst = (CARD8 *) dstBits; + + for (nbox = REGION_NUM_RECTS (pClip), + pbox = REGION_RECTS(pClip); + nbox--; + pbox++) + { + x1 = x; + y1 = y; + x2 = x + width; + y2 = y + height; + if (x1 < pbox->x1) + x1 = pbox->x1; + if (y1 < pbox->y1) + y1 = pbox->y1; + if (x2 > pbox->x2) + x2 = pbox->x2; + if (y2 > pbox->y2) + y2 = pbox->y2; + if (x1 >= x2 || y1 >= y2) + continue; + fb24_32BltDown (src + (y1 - y) * srcStride, + srcStride, + (x1 - x), + + dst + (y1 + dstYoff) * dstStride, + dstStride, + x1 + dstXoff, + + (x2 - x1), + (y2 - y1), + + alu, + pm); + } +} + +void +fb24_32GetImage (DrawablePtr pDrawable, + int x, + int y, + int w, + int h, + unsigned int format, + unsigned long planeMask, + char *d) +{ + FbBits *srcBits; + CARD8 *src; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + FbStride dstStride; + FbBits pm; + + fbGetDrawable (pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); + src = (CARD8 *) srcBits; + srcStride *= sizeof (FbBits); + + x += pDrawable->x; + y += pDrawable->y; + + pm = fbReplicatePixel (planeMask, 32); + dstStride = PixmapBytePad(w, pDrawable->depth); + if (pm != FB_ALLONES) + memset (d, 0, dstStride * h); + fb24_32BltUp (src + (y + srcYoff) * srcStride, srcStride, x + srcXoff, + (CARD8 *) d, dstStride, 0, + w, h, GXcopy, pm); +} + +void +fb24_32CopyMtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + FbBits *srcBits; + CARD8 *src; + FbStride srcStride; + int srcBpp; + FbBits *dstBits; + CARD8 *dst; + FbStride dstStride; + int dstBpp; + fb24_32BltFunc blt; + int srcXoff, srcYoff; + int dstXoff, dstYoff; + + fbGetDrawable (pSrcDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); + src = (CARD8 *) srcBits; + srcStride *= sizeof (FbBits); + fbGetDrawable (pDstDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + dst = (CARD8 *) dstBits; + dstStride *= sizeof (FbBits); + if (srcBpp == 24) + blt = fb24_32BltUp; + else + blt = fb24_32BltDown; + + while (nbox--) + { + (*blt) (src + (pbox->y1 + dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff), + + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff), + + (pbox->x2 - pbox->x1), + (pbox->y2 - pbox->y1), + + pGC->alu, + pPriv->pm); + pbox++; + } +} + +PixmapPtr +fb24_32ReformatTile(PixmapPtr pOldTile, int bitsPerPixel) +{ + ScreenPtr pScreen = pOldTile->drawable.pScreen; + PixmapPtr pNewTile; + FbBits *old, *new; + FbStride oldStride, newStride; + int oldBpp, newBpp; + fb24_32BltFunc blt; + int oldXoff, oldYoff; + int newXoff, newYoff; + + pNewTile = fbCreatePixmapBpp (pScreen, + pOldTile->drawable.width, + pOldTile->drawable.height, + pOldTile->drawable.depth, + bitsPerPixel); + if (!pNewTile) + return 0; + fbGetDrawable (&pOldTile->drawable, + old, oldStride, oldBpp, oldXoff, oldYoff); + fbGetDrawable (&pNewTile->drawable, + new, newStride, newBpp, newXoff, newYoff); + if (oldBpp == 24) + blt = fb24_32BltUp; + else + blt = fb24_32BltDown; + + (*blt) ((CARD8 *) old, + oldStride * sizeof (FbBits), + 0, + + (CARD8 *) new, + newStride * sizeof (FbBits), + 0, + + pOldTile->drawable.width, + pOldTile->drawable.height, + + GXcopy, + FB_ALLONES); + + return pNewTile; +} + +typedef struct { + pointer pbits; + int width; +} miScreenInitParmsRec, *miScreenInitParmsPtr; + +Bool +fb24_32CreateScreenResources(ScreenPtr pScreen) +{ + miScreenInitParmsPtr pScrInitParms; + int pitch; + Bool retval; + + /* get the pitch before mi destroys it */ + pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate; + pitch = BitmapBytePad(pScrInitParms->width * 24); + + if((retval = miCreateScreenResources(pScreen))) { + /* fix the screen pixmap */ + PixmapPtr pPix = (PixmapPtr)pScreen->devPrivate; + pPix->drawable.bitsPerPixel = 24; + pPix->devKind = pitch; + } + + return retval; +} + +Bool +fb24_32ModifyPixmapHeader (PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, + int devKind, + pointer pPixData) +{ + int bpp, w; + + if (!pPixmap) + return FALSE; + bpp = bitsPerPixel; + if (bpp <= 0) + bpp = pPixmap->drawable.bitsPerPixel; + if (bpp == 24) + { + if (devKind < 0) + { + w = width; + if (w <= 0) + w = pPixmap->drawable.width; + devKind = BitmapBytePad(w * 24); + } + } + return miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, + devKind, pPixData); +} diff --git a/fb/fb24_32.h b/fb/fb24_32.h new file mode 100644 index 000000000..d0a0acb97 --- /dev/null +++ b/fb/fb24_32.h @@ -0,0 +1,49 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fb24_32.h,v 1.1 2000/04/04 19:24:49 dawes Exp $ + * + * Copyright © 2000 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. + */ + +#ifndef _FB24_32_H_ +#define _FB24_32_H_ + +Bool +fb24_32FinishScreenInit(ScreenPtr pScreen, + pointer pbits, + int xsize, + int ysize, + int dpix, + int dpiy, + int width, + int bpp); + +Bool +fb24_32ScreenInit(ScreenPtr pScreen, + pointer pbits, + int xsize, + int ysize, + int dpix, + int dpiy, + int width, + int bpp); + +#endif diff --git a/fb/fballpriv.c b/fb/fballpriv.c new file mode 100644 index 000000000..687de493a --- /dev/null +++ b/fb/fballpriv.c @@ -0,0 +1,77 @@ +/* + * Id: fballpriv.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fballpriv.c,v 1.4 2000/05/06 21:09:31 keithp Exp $ */ + +#include "fb.h" + +#ifdef FB_SCREEN_PRIVATE +int fbScreenPrivateIndex; +#endif +int fbGCPrivateIndex; +#ifndef FB_NO_WINDOW_PIXMAPS +int fbWinPrivateIndex; +#endif +int fbGeneration; + +#ifdef FB_OLD_SCREEN +#define miAllocateGCPrivateIndex() AllocateGCPrivateIndex() +#endif + +Bool +fbAllocatePrivates(ScreenPtr pScreen, int *pGCIndex) +{ + if (fbGeneration != serverGeneration) + { + fbGCPrivateIndex = miAllocateGCPrivateIndex (); +#ifndef FB_NO_WINDOW_PIXMAPS + fbWinPrivateIndex = AllocateWindowPrivateIndex(); +#endif +#ifdef FB_SCREEN_PRIVATE + fbScreenPrivateIndex = AllocateScreenPrivateIndex (); + if (fbScreenPrivateIndex == -1) + return FALSE; +#endif + + fbGeneration = serverGeneration; + } + if (pGCIndex) + *pGCIndex = fbGCPrivateIndex; + if (!AllocateGCPrivate(pScreen, fbGCPrivateIndex, sizeof(FbGCPrivRec))) + return FALSE; +#ifndef FB_NO_WINDOW_PIXMAPS + if (!AllocateWindowPrivate(pScreen, fbWinPrivateIndex, 0)) + return FALSE; +#endif +#ifdef FB_SCREEN_PRIVATE + { + FbScreenPrivPtr pScreenPriv; + + pScreenPriv = (FbScreenPrivPtr) xalloc (sizeof (FbScreenPrivRec)); + if (!pScreenPriv) + return FALSE; + pScreen->devPrivates[fbScreenPrivateIndex].ptr = (pointer) pScreenPriv; + } +#endif + return TRUE; +} diff --git a/fb/fbarc.c b/fb/fbarc.c new file mode 100644 index 000000000..9713ffb09 --- /dev/null +++ b/fb/fbarc.c @@ -0,0 +1,118 @@ +/* + * Id: fbarc.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbarc.c,v 1.8 2002/11/09 04:59:29 tsi Exp $ */ + +#include "fb.h" +#include "mizerarc.h" +#ifdef IN_MODULE +#include "xf86_ansic.h" +#endif + +typedef void (*FbArc) (FbBits *dst, + FbStride dstStride, + int dstBpp, + xArc *arc, + int dx, + int dy, + FbBits and, + FbBits xor); + +void +fbPolyArc (DrawablePtr pDrawable, + GCPtr pGC, + int narcs, + xArc *parcs) +{ + FbArc arc; + + if (pGC->lineWidth == 0) + { +#ifndef FBNOPIXADDR + arc = 0; + if (pGC->lineStyle == LineSolid && pGC->fillStyle == FillSolid) + { + switch (pDrawable->bitsPerPixel) + { + case 8: arc = fbArc8; break; + case 16: arc = fbArc16; break; +#ifdef FB_24BIT + case 24: arc = fbArc24; break; +#endif + case 32: arc = fbArc32; break; + } + } + if (arc) + { + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + BoxRec box; + int x2, y2; + RegionPtr cclip; + + cclip = fbGetCompositeClip (pGC); + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + while (narcs--) + { + if (miCanZeroArc (parcs)) + { + box.x1 = parcs->x + pDrawable->x; + box.y1 = parcs->y + pDrawable->y; + /* + * Because box.x2 and box.y2 get truncated to 16 bits, and the + * RECT_IN_REGION test treats the resulting number as a signed + * integer, the RECT_IN_REGION test alone can go the wrong way. + * This can result in a server crash because the rendering + * routines in this file deal directly with cpu addresses + * of pixels to be stored, and do not clip or otherwise check + * that all such addresses are within their respective pixmaps. + * So we only allow the RECT_IN_REGION test to be used for + * values that can be expressed correctly in a signed short. + */ + x2 = box.x1 + (int)parcs->width + 1; + box.x2 = x2; + y2 = box.y1 + (int)parcs->height + 1; + box.y2 = y2; + if ( (x2 <= MAXSHORT) && (y2 <= MAXSHORT) && + (RECT_IN_REGION(pDrawable->pScreen, cclip, &box) == rgnIN) ) + (*arc) (dst, dstStride, dstBpp, + parcs, pDrawable->x + dstXoff, pDrawable->y + dstYoff, + pPriv->and, pPriv->xor); + else + miZeroPolyArc(pDrawable, pGC, 1, parcs); + } + else + miPolyArc(pDrawable, pGC, 1, parcs); + parcs++; + } + } + else +#endif + miZeroPolyArc (pDrawable, pGC, narcs, parcs); + } + else + miPolyArc (pDrawable, pGC, narcs, parcs); +} diff --git a/fb/fbbits.c b/fb/fbbits.c new file mode 100644 index 000000000..b1c123d21 --- /dev/null +++ b/fb/fbbits.c @@ -0,0 +1,175 @@ +/* + * Id: fbbits.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbbits.c,v 1.6 2000/02/23 20:29:41 dawes Exp $ */ + +#include "fb.h" +#include "miline.h" +#include "mizerarc.h" + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef GLYPH +#undef BITS +#undef BITS2 +#undef BITS4 + +#define BRESSOLID fbBresSolid8 +#define BRESDASH fbBresDash8 +#define DOTS fbDots8 +#define ARC fbArc8 +#define GLYPH fbGlyph8 +#define POLYLINE fbPolyline8 +#define POLYSEGMENT fbPolySegment8 +#define BITS BYTE +#define BITS2 CARD16 +#define BITS4 CARD32 + +#include "fbbits.h" + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef GLYPH +#undef POLYLINE +#undef POLYSEGMENT +#undef BITS +#undef BITS2 +#undef BITS4 + +#define BRESSOLID fbBresSolid16 +#define BRESDASH fbBresDash16 +#define DOTS fbDots16 +#define ARC fbArc16 +#define GLYPH fbGlyph16 +#define POLYLINE fbPolyline16 +#define POLYSEGMENT fbPolySegment16 +#define BITS CARD16 +#define BITS2 CARD32 +#if FB_SHIFT == 6 +#define BITS4 FbBits +#endif + +#include "fbbits.h" + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef GLYPH +#undef POLYLINE +#undef POLYSEGMENT +#undef BITS +#undef BITS2 +#if FB_SHIFT == 6 +#undef BITS4 +#endif + +#ifdef FB_24BIT +#define BRESSOLID fbBresSolid24 +#define BRESDASH fbBresDash24 +#define DOTS fbDots24 +#define ARC fbArc24 +#define POLYLINE fbPolyline24 +#define POLYSEGMENT fbPolySegment24 + +#define BITS CARD32 +#define BITSUNIT BYTE +#define BITSMUL 3 + +#define FbDoTypeStore(b,t,x,s) (*((t *) (b)) = (x) >> (s)) +#define FbDoTypeRRop(b,t,a,x,s) (*((t *) (b)) = FbDoRRop(*((t *) (b)),\ + (a) >> (s), \ + (x) >> (s))) +#define FbDoTypeMaskRRop(b,t,a,x,m,s) (*((t *) (b)) = FbDoMaskRRop(*((t *) (b)),\ + (a) >> (s), \ + (x) >> (s), \ + (m) >> (s)) +#if BITMAP_BIT_ORDER == LSBFirst +#define BITSSTORE(b,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeStore (b, CARD8, x, 0), \ + FbDoTypeStore ((b) + 1, CARD16, x, 8)) : \ + (FbDoTypeStore (b, CARD16, x, 0), \ + FbDoTypeStore ((b) + 2, CARD8, x, 16))) +#define BITSRROP(b,a,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeRRop(b,CARD8,a,x,0), \ + FbDoTypeRRop((b)+1,CARD16,a,x,8)) : \ + (FbDoTypeRRop(b,CARD16,a,x,0), \ + FbDoTypeRRop((b)+2,CARD8,a,x,16))) +#else +#define BITSSTORE(b,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeStore (b, CARD8, x, 16), \ + FbDoTypeStore ((b) + 1, CARD16, x, 0)) : \ + (FbDoTypeStore (b, CARD16, x, 8), \ + FbDoTypeStore ((b) + 2, CARD8, x, 0))) +#define BITSRROP(b,a,x) ((unsigned long) (b) & 1 ? \ + (FbDoTypeRRop (b, CARD8, a, x, 16), \ + FbDoTypeRRop ((b) + 1, CARD16, a, x, 0)) : \ + (FbDoTypeRRop (b, CARD16, a, x, 8), \ + FbDoTypeRRop ((b) + 2, CARD8, a, x, 0))) +#endif + +#include "fbbits.h" + +#undef BITSSTORE +#undef BITSRROP +#undef BITSMUL +#undef BITSUNIT +#undef BITS + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef POLYLINE +#undef POLYSEGMENT +#endif /* FB_24BIT */ + +#define BRESSOLID fbBresSolid32 +#define BRESDASH fbBresDash32 +#define DOTS fbDots32 +#define ARC fbArc32 +#define GLYPH fbGlyph32 +#define POLYLINE fbPolyline32 +#define POLYSEGMENT fbPolySegment32 +#define BITS CARD32 +#if FB_SHIFT == 6 +#define BITS2 FbBits +#endif + +#include "fbbits.h" + +#undef BRESSOLID +#undef BRESDASH +#undef DOTS +#undef ARC +#undef GLYPH +#undef POLYLINE +#undef POLYSEGMENT +#undef BITS +#if FB_SHIFT == 6 +#undef BITS2 +#endif diff --git a/fb/fbbits.h b/fb/fbbits.h new file mode 100644 index 000000000..515e179ac --- /dev/null +++ b/fb/fbbits.h @@ -0,0 +1,959 @@ +/* + * Id: fbbits.h,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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbbits.h,v 1.13 2001/11/18 05:00:25 torrey Exp $ */ + +/* + * This file defines functions for drawing some primitives using + * underlying datatypes instead of masks + */ + +#define isClipped(c,ul,lr) ((((c) - (ul)) | ((lr) - (c))) & 0x80008000) + +#ifdef BITSMUL +#define MUL BITSMUL +#else +#define MUL 1 +#endif + +#ifdef BITSSTORE +#define STORE(b,x) BITSSTORE(b,x) +#else +#define STORE(b,x) (*(b) = (x)) +#endif + +#ifdef BITSRROP +#define RROP(b,a,x) BITSRROP(b,a,x) +#else +#define RROP(b,a,x) (*(b) = FbDoRRop (*(b), (a), (x))) +#endif + +#ifdef BITSUNIT +#define UNIT BITSUNIT +#define USE_SOLID +#else +#define UNIT BITS +#endif + +/* + * Define the following before including this file: + * + * BRESSOLID name of function for drawing a solid segment + * BRESDASH name of function for drawing a dashed segment + * DOTS name of function for drawing dots + * ARC name of function for drawing a solid arc + * BITS type of underlying unit + */ + +#ifdef BRESSOLID +void +BRESSOLID (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + UNIT *bits; + FbStride bitsStride; + FbStride majorStep, minorStep; + BITS xor = (BITS) pPriv->xor; + + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + bits = ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff) * MUL; + bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT)); + if (signdy < 0) + bitsStride = -bitsStride; + if (axis == X_AXIS) + { + majorStep = signdx * MUL; + minorStep = bitsStride; + } + else + { + majorStep = bitsStride; + minorStep = signdx * MUL; + } + while (len--) + { + STORE(bits,xor); + bits += majorStep; + e += e1; + if (e >= 0) + { + bits += minorStep; + e += e3; + } + } +} +#endif + +#ifdef BRESDASH +void +BRESDASH (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + UNIT *bits; + FbStride bitsStride; + FbStride majorStep, minorStep; + BITS xorfg, xorbg; + FbDashDeclare; + int dashlen; + Bool even; + Bool doOdd; + + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + doOdd = pGC->lineStyle == LineDoubleDash; + xorfg = (BITS) pPriv->xor; + xorbg = (BITS) pPriv->bgxor; + + FbDashInit (pGC, pPriv, dashOffset, dashlen, even); + + bits = ((UNIT *) (dst + ((y1 + dstYoff) * dstStride))) + (x1 + dstXoff) * MUL; + bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT)); + if (signdy < 0) + bitsStride = -bitsStride; + if (axis == X_AXIS) + { + majorStep = signdx * MUL; + minorStep = bitsStride; + } + else + { + majorStep = bitsStride; + minorStep = signdx * MUL; + } + if (dashlen >= len) + dashlen = len; + if (doOdd) + { + if (!even) + goto doubleOdd; + for (;;) + { + len -= dashlen; + while (dashlen--) + { + STORE(bits,xorfg); + bits += majorStep; + if ((e += e1) >= 0) + { + e += e3; + bits += minorStep; + } + } + if (!len) + break; + + FbDashNextEven(dashlen); + + if (dashlen >= len) + dashlen = len; +doubleOdd: + len -= dashlen; + while (dashlen--) + { + STORE(bits,xorbg); + bits += majorStep; + if ((e += e1) >= 0) + { + e += e3; + bits += minorStep; + } + } + if (!len) + break; + + FbDashNextOdd(dashlen); + + if (dashlen >= len) + dashlen = len; + } + } + else + { + if (!even) + goto onOffOdd; + for (;;) + { + len -= dashlen; + while (dashlen--) + { + STORE(bits,xorfg); + bits += majorStep; + if ((e += e1) >= 0) + { + e += e3; + bits += minorStep; + } + } + if (!len) + break; + + FbDashNextEven (dashlen); + + if (dashlen >= len) + dashlen = len; +onOffOdd: + len -= dashlen; + while (dashlen--) + { + bits += majorStep; + if ((e += e1) >= 0) + { + e += e3; + bits += minorStep; + } + } + if (!len) + break; + + FbDashNextOdd (dashlen); + + if (dashlen >= len) + dashlen = len; + } + } +} +#endif + +#ifdef DOTS +void +DOTS (FbBits *dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint *ptsOrig, + int npt, + int xoff, + int yoff, + FbBits and, + FbBits xor) +{ + INT32 *pts = (INT32 *) ptsOrig; + UNIT *bits = (UNIT *) dst; + UNIT *point; + BITS bxor = (BITS) xor; + BITS band = (BITS) and; + FbStride bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT)); + INT32 ul, lr; + INT32 pt; + + ul = coordToInt(pBox->x1 - xoff, pBox->y1 - yoff); + lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1); + + bits += bitsStride * yoff + xoff * MUL; + + if (and == 0) + { + while (npt--) + { + pt = *pts++; + if (!isClipped(pt,ul,lr)) + { + point = bits + intToY(pt) * bitsStride + intToX(pt) * MUL; + STORE(point,bxor); + } + } + } + else + { + while (npt--) + { + pt = *pts++; + if (!isClipped(pt,ul,lr)) + { + point = bits + intToY(pt) * bitsStride + intToX(pt) * MUL; + RROP(point,band,bxor); + } + } + } +} +#endif + +#ifdef ARC + +#define ARCCOPY(d) STORE(d,xorBits) +#define ARCRROP(d) RROP(d,andBits,xorBits) + +void +ARC (FbBits *dst, + FbStride dstStride, + int dstBpp, + xArc *arc, + int drawX, + int drawY, + FbBits and, + FbBits xor) +{ + UNIT *bits; + FbStride bitsStride; + miZeroArcRec info; + Bool do360; + int x; + UNIT *yorgp, *yorgop; + BITS andBits, xorBits; + int yoffset, dyoffset; + int y, a, b, d, mask; + int k1, k3, dx, dy; + + bits = (UNIT *) dst; + bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT)); + andBits = (BITS) and; + xorBits = (BITS) xor; + do360 = miZeroArcSetup(arc, &info, TRUE); + yorgp = bits + ((info.yorg + drawY) * bitsStride); + yorgop = bits + ((info.yorgo + drawY) * bitsStride); + info.xorg = (info.xorg + drawX) * MUL; + info.xorgo = (info.xorgo + drawX) * MUL; + MIARCSETUP(); + yoffset = y ? bitsStride : 0; + dyoffset = 0; + mask = info.initialMask; + + if (!(arc->width & 1)) + { + if (andBits == 0) + { + if (mask & 2) + ARCCOPY(yorgp + info.xorgo); + if (mask & 8) + ARCCOPY(yorgop + info.xorgo); + } + else + { + if (mask & 2) + ARCRROP(yorgp + info.xorgo); + if (mask & 8) + ARCRROP(yorgop + info.xorgo); + } + } + if (!info.end.x || !info.end.y) + { + mask = info.end.mask; + info.end = info.altend; + } + if (do360 && (arc->width == arc->height) && !(arc->width & 1)) + { + int xoffset = bitsStride; + UNIT *yorghb = yorgp + (info.h * bitsStride) + info.xorg; + UNIT *yorgohb = yorghb - info.h * MUL; + + yorgp += info.xorg; + yorgop += info.xorg; + yorghb += info.h * MUL; + while (1) + { + if (andBits == 0) + { + ARCCOPY(yorgp + yoffset + x * MUL); + ARCCOPY(yorgp + yoffset - x * MUL); + ARCCOPY(yorgop - yoffset - x * MUL); + ARCCOPY(yorgop - yoffset + x * MUL); + } + else + { + ARCRROP(yorgp + yoffset + x * MUL); + ARCRROP(yorgp + yoffset - x * MUL); + ARCRROP(yorgop - yoffset - x * MUL); + ARCRROP(yorgop - yoffset + x * MUL); + } + if (a < 0) + break; + if (andBits == 0) + { + ARCCOPY(yorghb - xoffset - y * MUL); + ARCCOPY(yorgohb - xoffset + y * MUL); + ARCCOPY(yorgohb + xoffset + y * MUL); + ARCCOPY(yorghb + xoffset - y * MUL); + } + else + { + ARCRROP(yorghb - xoffset - y * MUL); + ARCRROP(yorgohb - xoffset + y * MUL); + ARCRROP(yorgohb + xoffset + y * MUL); + ARCRROP(yorghb + xoffset - y * MUL); + } + xoffset += bitsStride; + MIARCCIRCLESTEP(yoffset += bitsStride;); + } + yorgp -= info.xorg; + yorgop -= info.xorg; + x = info.w; + yoffset = info.h * bitsStride; + } + else if (do360) + { + while (y < info.h || x < info.w) + { + MIARCOCTANTSHIFT(dyoffset = bitsStride;); + if (andBits == 0) + { + ARCCOPY(yorgp + yoffset + info.xorg + x * MUL); + ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL); + ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL); + ARCCOPY(yorgop - yoffset + info.xorg + x * MUL); + } + else + { + ARCRROP(yorgp + yoffset + info.xorg + x * MUL); + ARCRROP(yorgp + yoffset + info.xorgo - x * MUL); + ARCRROP(yorgop - yoffset + info.xorgo - x * MUL); + ARCRROP(yorgop - yoffset + info.xorg + x * MUL); + } + MIARCSTEP(yoffset += dyoffset;, yoffset += bitsStride;); + } + } + else + { + while (y < info.h || x < info.w) + { + MIARCOCTANTSHIFT(dyoffset = bitsStride;); + if ((x == info.start.x) || (y == info.start.y)) + { + mask = info.start.mask; + info.start = info.altstart; + } + if (andBits == 0) + { + if (mask & 1) + ARCCOPY(yorgp + yoffset + info.xorg + x * MUL); + if (mask & 2) + ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL); + if (mask & 4) + ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL); + if (mask & 8) + ARCCOPY(yorgop - yoffset + info.xorg + x * MUL); + } + else + { + if (mask & 1) + ARCRROP(yorgp + yoffset + info.xorg + x * MUL); + if (mask & 2) + ARCRROP(yorgp + yoffset + info.xorgo - x * MUL); + if (mask & 4) + ARCRROP(yorgop - yoffset + info.xorgo - x * MUL); + if (mask & 8) + ARCRROP(yorgop - yoffset + info.xorg + x * MUL); + } + if ((x == info.end.x) || (y == info.end.y)) + { + mask = info.end.mask; + info.end = info.altend; + } + MIARCSTEP(yoffset += dyoffset;, yoffset += bitsStride;); + } + } + if ((x == info.start.x) || (y == info.start.y)) + mask = info.start.mask; + if (andBits == 0) + { + if (mask & 1) + ARCCOPY(yorgp + yoffset + info.xorg + x * MUL); + if (mask & 4) + ARCCOPY(yorgop - yoffset + info.xorgo - x * MUL); + if (arc->height & 1) + { + if (mask & 2) + ARCCOPY(yorgp + yoffset + info.xorgo - x * MUL); + if (mask & 8) + ARCCOPY(yorgop - yoffset + info.xorg + x * MUL); + } + } + else + { + if (mask & 1) + ARCRROP(yorgp + yoffset + info.xorg + x * MUL); + if (mask & 4) + ARCRROP(yorgop - yoffset + info.xorgo - x * MUL); + if (arc->height & 1) + { + if (mask & 2) + ARCRROP(yorgp + yoffset + info.xorgo - x * MUL); + if (mask & 8) + ARCRROP(yorgop - yoffset + info.xorg + x * MUL); + } + } +} +#undef ARCCOPY +#undef ARCRROP +#endif + +#ifdef GLYPH +#if BITMAP_BIT_ORDER == LSBFirst +# define WRITE_ADDR1(n) (n) +# define WRITE_ADDR2(n) (n) +# define WRITE_ADDR4(n) (n) +#else +# define WRITE_ADDR1(n) ((n) ^ 3) +# define WRITE_ADDR2(n) ((n) ^ 2) +# define WRITE_ADDR4(n) ((n)) +#endif + +#define WRITE1(d,n,fg) ((d)[WRITE_ADDR1(n)] = (BITS) (fg)) + +#ifdef BITS2 +# define WRITE2(d,n,fg) (*((BITS2 *) &((d)[WRITE_ADDR2(n)])) = (BITS2) (fg)) +#else +# define WRITE2(d,n,fg) WRITE1(d,(n)+1,WRITE1(d,n,fg)) +#endif + +#ifdef BITS4 +# define WRITE4(d,n,fg) (*((BITS4 *) &((d)[WRITE_ADDR4(n)])) = (BITS4) (fg)) +#else +# define WRITE4(d,n,fg) WRITE2(d,(n)+2,WRITE2(d,n,fg)) +#endif + +void +GLYPH (FbBits *dstBits, + FbStride dstStride, + int dstBpp, + FbStip *stipple, + FbBits fg, + int x, + int height) +{ + int lshift; + FbStip bits; + BITS *dstLine; + BITS *dst; + int n; + int shift; + + dstLine = (BITS *) dstBits; + dstLine += x & ~3; + dstStride *= (sizeof (FbBits) / sizeof (BITS)); + shift = x & 3; + lshift = 4 - shift; + while (height--) + { + bits = *stipple++; + dst = (BITS *) dstLine; + n = lshift; + while (bits) + { + switch (FbStipMoveLsb (FbLeftStipBits (bits, n), 4, n)) { + case 0: + break; + case 1: + WRITE1(dst,0,fg); + break; + case 2: + WRITE1(dst,1,fg); + break; + case 3: + WRITE2(dst,0,fg); + break; + case 4: + WRITE1(dst,2,fg); + break; + case 5: + WRITE1(dst,0,fg); + WRITE1(dst,2,fg); + break; + case 6: + WRITE1(dst,1,fg); + WRITE1(dst,2,fg); + break; + case 7: + WRITE2(dst,0,fg); + WRITE1(dst,2,fg); + break; + case 8: + WRITE1(dst,3,fg); + break; + case 9: + WRITE1(dst,0,fg); + WRITE1(dst,3,fg); + break; + case 10: + WRITE1(dst,1,fg); + WRITE1(dst,3,fg); + break; + case 11: + WRITE2(dst,0,fg); + WRITE1(dst,3,fg); + break; + case 12: + WRITE2(dst,2,fg); + break; + case 13: + WRITE1(dst,0,fg); + WRITE2(dst,2,fg); + break; + case 14: + WRITE1(dst,1,fg); + WRITE2(dst,2,fg); + break; + case 15: + WRITE4(dst,0,fg); + break; + } + bits = FbStipLeft (bits, n); + n = 4; + dst += 4; + } + dstLine += dstStride; + } +} +#undef WRITE_ADDR1 +#undef WRITE_ADDR2 +#undef WRITE_ADDR4 +#undef WRITE1 +#undef WRITE2 +#undef WRITE4 + +#endif + +#ifdef POLYLINE +void +POLYLINE (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ptsOrig) +{ + INT32 *pts = (INT32 *) ptsOrig; + int xoff = pDrawable->x; + int yoff = pDrawable->y; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + BoxPtr pBox = REGION_EXTENTS (pDrawable->pScreen, fbGetCompositeClip (pGC)); + + FbBits *dst; + int dstStride; + int dstBpp; + int dstXoff, dstYoff; + + UNIT *bits, *bitsBase; + FbStride bitsStride; + BITS xor = fbGetGCPrivate(pGC)->xor; + BITS and = fbGetGCPrivate(pGC)->and; + int dashoffset = 0; + + INT32 ul, lr; + INT32 pt1, pt2; + + int e, e1, e3, len; + int stepmajor, stepminor; + int octant; + + if (mode == CoordModePrevious) + fbFixCoordModePrevious (npt, ptsOrig); + + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT)); + bitsBase = ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff) * MUL; + ul = coordToInt(pBox->x1 - xoff, pBox->y1 - yoff); + lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1); + + pt1 = *pts++; + npt--; + pt2 = *pts++; + npt--; + for (;;) + { + if (isClipped (pt1, ul, lr) | isClipped (pt2, ul, lr)) + { + fbSegment (pDrawable, pGC, + intToX(pt1) + xoff, intToY(pt1) + yoff, + intToX(pt2) + xoff, intToY(pt2) + yoff, + npt == 0 && pGC->capStyle != CapNotLast, + &dashoffset); + if (!npt) + return; + pt1 = pt2; + pt2 = *pts++; + npt--; + } + else + { + bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1) * MUL; + for (;;) + { + CalcLineDeltas (intToX(pt1), intToY(pt1), + intToX(pt2), intToY(pt2), + len, e1, stepmajor, stepminor, 1, bitsStride, + octant); + stepmajor *= MUL; + if (len < e1) + { + e3 = len; + len = e1; + e1 = e3; + + e3 = stepminor; + stepminor = stepmajor; + stepmajor = e3; + SetYMajorOctant(octant); + } + e = -len; + e1 <<= 1; + e3 = e << 1; + FIXUP_ERROR (e, octant, bias); + if (and == 0) + { + while (len--) + { + STORE(bits,xor); + bits += stepmajor; + e += e1; + if (e >= 0) + { + bits += stepminor; + e += e3; + } + } + } + else + { + while (len--) + { + RROP(bits,and,xor); + bits += stepmajor; + e += e1; + if (e >= 0) + { + bits += stepminor; + e += e3; + } + } + } + if (!npt) + { + if (pGC->capStyle != CapNotLast && + pt2 != *((INT32 *) ptsOrig)) + { + RROP(bits,and,xor); + } + return; + } + pt1 = pt2; + pt2 = *pts++; + --npt; + if (isClipped (pt2, ul, lr)) + break; + } + } + } +} +#endif + +#ifdef POLYSEGMENT +void +POLYSEGMENT (DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pseg) +{ + INT32 *pts = (INT32 *) pseg; + int xoff = pDrawable->x; + int yoff = pDrawable->y; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + BoxPtr pBox = REGION_EXTENTS (pDrawable->pScreen, fbGetCompositeClip (pGC)); + + FbBits *dst; + int dstStride; + int dstBpp; + int dstXoff, dstYoff; + + UNIT *bits, *bitsBase; + FbStride bitsStride; + FbBits xorBits = fbGetGCPrivate(pGC)->xor; + FbBits andBits = fbGetGCPrivate(pGC)->and; + BITS xor = xorBits; + BITS and = andBits; + int dashoffset = 0; + + INT32 ul, lr; + INT32 pt1, pt2; + + int e, e1, e3, len; + int stepmajor, stepminor; + int octant; + Bool capNotLast; + + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + bitsStride = dstStride * (sizeof (FbBits) / sizeof (UNIT)); + bitsBase = ((UNIT *) dst) + (yoff + dstYoff) * bitsStride + (xoff + dstXoff) * MUL; + ul = coordToInt(pBox->x1 - xoff, pBox->y1 - yoff); + lr = coordToInt(pBox->x2 - xoff - 1, pBox->y2 - yoff - 1); + + bits += bitsStride * yoff + xoff * MUL; + + capNotLast = pGC->capStyle == CapNotLast; + + while (nseg--) + { + pt1 = *pts++; + pt2 = *pts++; + if (isClipped (pt1, ul, lr) | isClipped (pt2, ul, lr)) + { + fbSegment (pDrawable, pGC, + intToX(pt1) + xoff, intToY(pt1) + yoff, + intToX(pt2) + xoff, intToY(pt2) + yoff, + !capNotLast, &dashoffset); + } + else + { + CalcLineDeltas (intToX(pt1), intToY(pt1), + intToX(pt2), intToY(pt2), + len, e1, stepmajor, stepminor, 1, bitsStride, + octant); + if (e1 == 0 && len > 3 +#if MUL != 1 + && FbCheck24Pix(and) && FbCheck24Pix(xor) +#endif + ) + { + int x1, x2; + FbBits *dstLine; + int dstX, width; + FbBits startmask, endmask; + int nmiddle; + + if (stepmajor < 0) + { + x1 = intToX(pt2); + x2 = intToX(pt1) + 1; + if (capNotLast) + x1++; + } + else + { + x1 = intToX(pt1); + x2 = intToX(pt2); + if (!capNotLast) + x2++; + } + dstX = (x1 + xoff + dstXoff) * (sizeof (UNIT) * 8 * MUL); + width = (x2 - x1) * (sizeof (UNIT) * 8 * MUL); + + dstLine = dst + (intToY(pt1) + yoff + dstYoff) * dstStride; + dstLine += dstX >> FB_SHIFT; + dstX &= FB_MASK; + FbMaskBits (dstX, width, startmask, nmiddle, endmask); + if (startmask) + { + *dstLine = FbDoMaskRRop (*dstLine, andBits, xorBits, startmask); + dstLine++; + } + if (!andBits) + while (nmiddle--) + *dstLine++ = xorBits; + else + while (nmiddle--) + { + *dstLine = FbDoRRop (*dstLine, andBits, xorBits); + dstLine++; + } + if (endmask) + *dstLine = FbDoMaskRRop (*dstLine, andBits, xorBits, endmask); + } + else + { + stepmajor *= MUL; + bits = bitsBase + intToY(pt1) * bitsStride + intToX(pt1) * MUL; + if (len < e1) + { + e3 = len; + len = e1; + e1 = e3; + + e3 = stepminor; + stepminor = stepmajor; + stepmajor = e3; + SetYMajorOctant(octant); + } + e = -len; + e1 <<= 1; + e3 = e << 1; + FIXUP_ERROR (e, octant, bias); + if (!capNotLast) + len++; + if (and == 0) + { + while (len--) + { + STORE(bits,xor); + bits += stepmajor; + e += e1; + if (e >= 0) + { + bits += stepminor; + e += e3; + } + } + } + else + { + while (len--) + { + RROP(bits,and,xor); + bits += stepmajor; + e += e1; + if (e >= 0) + { + bits += stepminor; + e += e3; + } + } + } + } + } + } +} +#endif + +#undef MUL +#undef STORE +#undef RROP +#undef UNIT +#undef USE_SOLID + +#undef isClipped diff --git a/fb/fbblt.c b/fb/fbblt.c new file mode 100644 index 000000000..b1fd5f5b0 --- /dev/null +++ b/fb/fbblt.c @@ -0,0 +1,926 @@ +/* + * Id: fbblt.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbblt.c,v 1.8 2000/09/28 00:47:22 keithp Exp $ */ + +#include "fb.h" + +#define InitializeShifts(sx,dx,ls,rs) { \ + if (sx != dx) { \ + if (sx > dx) { \ + ls = sx - dx; \ + rs = FB_UNIT - ls; \ + } else { \ + rs = dx - sx; \ + ls = FB_UNIT - rs; \ + } \ + } \ +} + +void +fbBlt (FbBits *srcLine, + FbStride srcStride, + int srcX, + + FbBits *dstLine, + FbStride dstStride, + int dstX, + + int width, + int height, + + int alu, + FbBits pm, + int bpp, + + Bool reverse, + Bool upsidedown) +{ + FbBits *src, *dst; + int leftShift, rightShift; + FbBits startmask, endmask; + FbBits bits, bits1; + int n, nmiddle; + Bool destInvarient; + int startbyte, endbyte; + FbDeclareMergeRop (); + +#ifdef FB_24BIT + if (bpp == 24 && !FbCheck24Pix (pm)) + { + fbBlt24 (srcLine, srcStride, srcX, dstLine, dstStride, dstX, + width, height, alu, pm, reverse, upsidedown); + return; + } +#endif + FbInitializeMergeRop(alu, pm); + destInvarient = FbDestInvarientMergeRop(); + if (upsidedown) + { + srcLine += (height - 1) * (srcStride); + dstLine += (height - 1) * (dstStride); + srcStride = -srcStride; + dstStride = -dstStride; + } + FbMaskBitsBytes (dstX, width, destInvarient, startmask, startbyte, + nmiddle, endmask, endbyte); + if (reverse) + { + srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1; + dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1; + srcX = (srcX + width - 1) & FB_MASK; + dstX = (dstX + width - 1) & FB_MASK; + } + else + { + srcLine += srcX >> FB_SHIFT; + dstLine += dstX >> FB_SHIFT; + srcX &= FB_MASK; + dstX &= FB_MASK; + } + if (srcX == dstX) + { + while (height--) + { + src = srcLine; + srcLine += srcStride; + dst = dstLine; + dstLine += dstStride; + if (reverse) + { + if (endmask) + { + bits = *--src; + --dst; + FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); + } + n = nmiddle; + if (destInvarient) + { + while (n--) + *--dst = FbDoDestInvarientMergeRop(*--src); + } + else + { + while (n--) + { + bits = *--src; + --dst; + *dst = FbDoMergeRop (bits, *dst); + } + } + if (startmask) + { + bits = *--src; + --dst; + FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); + } + } + else + { + if (startmask) + { + bits = *src++; + FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask); + dst++; + } + n = nmiddle; + if (destInvarient) + { +#if 0 + /* + * This provides some speedup on screen->screen blts + * over the PCI bus, usually about 10%. But fb + * isn't usually used for this operation... + */ + if (_ca2 + 1 == 0 && _cx2 == 0) + { + FbBits t1, t2, t3, t4; + while (n >= 4) + { + t1 = *src++; + t2 = *src++; + t3 = *src++; + t4 = *src++; + *dst++ = t1; + *dst++ = t2; + *dst++ = t3; + *dst++ = t4; + n -= 4; + } + } +#endif + while (n--) + *dst++ = FbDoDestInvarientMergeRop(*src++); + } + else + { + while (n--) + { + bits = *src++; + *dst = FbDoMergeRop (bits, *dst); + dst++; + } + } + if (endmask) + { + bits = *src; + FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); + } + } + } + } + else + { + if (srcX > dstX) + { + leftShift = srcX - dstX; + rightShift = FB_UNIT - leftShift; + } + else + { + rightShift = dstX - srcX; + leftShift = FB_UNIT - rightShift; + } + while (height--) + { + src = srcLine; + srcLine += srcStride; + dst = dstLine; + dstLine += dstStride; + + bits1 = 0; + if (reverse) + { + if (srcX < dstX) + bits1 = *--src; + if (endmask) + { + bits = FbScrRight(bits1, rightShift); + if (FbScrRight(endmask, leftShift)) + { + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + } + --dst; + FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask); + } + n = nmiddle; + if (destInvarient) + { + while (n--) + { + bits = FbScrRight(bits1, rightShift); + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + --dst; + *dst = FbDoDestInvarientMergeRop(bits); + } + } + else + { + while (n--) + { + bits = FbScrRight(bits1, rightShift); + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + --dst; + *dst = FbDoMergeRop(bits, *dst); + } + } + if (startmask) + { + bits = FbScrRight(bits1, rightShift); + if (FbScrRight(startmask, leftShift)) + { + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + } + --dst; + FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask); + } + } + else + { + if (srcX > dstX) + bits1 = *src++; + if (startmask) + { + bits = FbScrLeft(bits1, leftShift); + bits1 = *src++; + bits |= FbScrRight(bits1, rightShift); + FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask); + dst++; + } + n = nmiddle; + if (destInvarient) + { + while (n--) + { + bits = FbScrLeft(bits1, leftShift); + bits1 = *src++; + bits |= FbScrRight(bits1, rightShift); + *dst = FbDoDestInvarientMergeRop(bits); + dst++; + } + } + else + { + while (n--) + { + bits = FbScrLeft(bits1, leftShift); + bits1 = *src++; + bits |= FbScrRight(bits1, rightShift); + *dst = FbDoMergeRop(bits, *dst); + dst++; + } + } + if (endmask) + { + bits = FbScrLeft(bits1, leftShift); + if (FbScrLeft(endmask, rightShift)) + { + bits1 = *src; + bits |= FbScrRight(bits1, rightShift); + } + FbDoRightMaskByteMergeRop (dst, bits, endbyte, endmask); + } + } + } + } +} + +#ifdef FB_24BIT + +#undef DEBUG_BLT24 +#ifdef DEBUG_BLT24 + +static unsigned long +getPixel (char *src, int x) +{ + unsigned long l; + + l = 0; + memcpy (&l, src + x * 3, 3); + return l; +} +#endif + +static void +fbBlt24Line (FbBits *src, + int srcX, + + FbBits *dst, + int dstX, + + int width, + + int alu, + FbBits pm, + + Bool reverse) +{ +#ifdef DEBUG_BLT24 + char *origDst = (char *) dst; + FbBits *origLine = dst + ((dstX >> FB_SHIFT) - 1); + int origNlw = ((width + FB_MASK) >> FB_SHIFT) + 3; + int origX = dstX / 24; +#endif + + int leftShift, rightShift; + FbBits startmask, endmask; + int n; + + FbBits bits, bits1; + FbBits mask; + + int rot; + FbDeclareMergeRop (); + + FbInitializeMergeRop (alu, FB_ALLONES); + FbMaskBits(dstX, width, startmask, n, endmask); +#ifdef DEBUG_BLT24 + ErrorF ("dstX %d width %d reverse %d\n", dstX, width, reverse); +#endif + if (reverse) + { + src += ((srcX + width - 1) >> FB_SHIFT) + 1; + dst += ((dstX + width - 1) >> FB_SHIFT) + 1; + rot = FbFirst24Rot (((dstX + width - 8) & FB_MASK)); + rot = FbPrev24Rot(rot); +#ifdef DEBUG_BLT24 + ErrorF ("dstX + width - 8: %d rot: %d\n", (dstX + width - 8) & FB_MASK, rot); +#endif + srcX = (srcX + width - 1) & FB_MASK; + dstX = (dstX + width - 1) & FB_MASK; + } + else + { + src += srcX >> FB_SHIFT; + dst += dstX >> FB_SHIFT; + srcX &= FB_MASK; + dstX &= FB_MASK; + rot = FbFirst24Rot (dstX); +#ifdef DEBUG_BLT24 + ErrorF ("dstX: %d rot: %d\n", dstX, rot); +#endif + } + mask = FbRot24(pm,rot); +#ifdef DEBUG_BLT24 + ErrorF ("pm 0x%x mask 0x%x\n", pm, mask); +#endif + if (srcX == dstX) + { + if (reverse) + { + if (endmask) + { + bits = *--src; + --dst; + *dst = FbDoMaskMergeRop (bits, *dst, mask & endmask); + mask = FbPrev24Pix (mask); + } + while (n--) + { + bits = *--src; + --dst; + *dst = FbDoMaskMergeRop (bits, *dst, mask); + mask = FbPrev24Pix (mask); + } + if (startmask) + { + bits = *--src; + --dst; + *dst = FbDoMaskMergeRop(bits, *dst, mask & startmask); + } + } + else + { + if (startmask) + { + bits = *src++; + *dst = FbDoMaskMergeRop (bits, *dst, mask & startmask); + dst++; + mask = FbNext24Pix(mask); + } + while (n--) + { + bits = *src++; + *dst = FbDoMaskMergeRop (bits, *dst, mask); + dst++; + mask = FbNext24Pix(mask); + } + if (endmask) + { + bits = *src; + *dst = FbDoMaskMergeRop(bits, *dst, mask & endmask); + } + } + } + else + { + if (srcX > dstX) + { + leftShift = srcX - dstX; + rightShift = FB_UNIT - leftShift; + } + else + { + rightShift = dstX - srcX; + leftShift = FB_UNIT - rightShift; + } + + bits1 = 0; + if (reverse) + { + if (srcX < dstX) + bits1 = *--src; + if (endmask) + { + bits = FbScrRight(bits1, rightShift); + if (FbScrRight(endmask, leftShift)) + { + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + } + --dst; + *dst = FbDoMaskMergeRop (bits, *dst, mask & endmask); + mask = FbPrev24Pix(mask); + } + while (n--) + { + bits = FbScrRight(bits1, rightShift); + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + --dst; + *dst = FbDoMaskMergeRop(bits, *dst, mask); + mask = FbPrev24Pix(mask); + } + if (startmask) + { + bits = FbScrRight(bits1, rightShift); + if (FbScrRight(startmask, leftShift)) + { + bits1 = *--src; + bits |= FbScrLeft(bits1, leftShift); + } + --dst; + *dst = FbDoMaskMergeRop (bits, *dst, mask & startmask); + } + } + else + { + if (srcX > dstX) + bits1 = *src++; + if (startmask) + { + bits = FbScrLeft(bits1, leftShift); + bits1 = *src++; + bits |= FbScrRight(bits1, rightShift); + *dst = FbDoMaskMergeRop (bits, *dst, mask & startmask); + dst++; + mask = FbNext24Pix(mask); + } + while (n--) + { + bits = FbScrLeft(bits1, leftShift); + bits1 = *src++; + bits |= FbScrRight(bits1, rightShift); + *dst = FbDoMaskMergeRop(bits, *dst, mask); + dst++; + mask = FbNext24Pix(mask); + } + if (endmask) + { + bits = FbScrLeft(bits1, leftShift); + if (FbScrLeft(endmask, rightShift)) + { + bits1 = *src; + bits |= FbScrRight(bits1, rightShift); + } + *dst = FbDoMaskMergeRop (bits, *dst, mask & endmask); + } + } + } +#ifdef DEBUG_BLT24 + { + int firstx, lastx, x; + + firstx = origX; + if (firstx) + firstx--; + lastx = origX + width/24 + 1; + for (x = firstx; x <= lastx; x++) + ErrorF ("%06x ", getPixel (origDst, x)); + ErrorF ("\n"); + while (origNlw--) + ErrorF ("%08x ", *origLine++); + ErrorF ("\n"); + } +#endif +} + +void +fbBlt24 (FbBits *srcLine, + FbStride srcStride, + int srcX, + + FbBits *dstLine, + FbStride dstStride, + int dstX, + + int width, + int height, + + int alu, + FbBits pm, + + Bool reverse, + Bool upsidedown) +{ + if (upsidedown) + { + srcLine += (height-1) * srcStride; + dstLine += (height-1) * dstStride; + srcStride = -srcStride; + dstStride = -dstStride; + } + while (height--) + { + fbBlt24Line (srcLine, srcX, dstLine, dstX, width, alu, pm, reverse); + srcLine += srcStride; + dstLine += dstStride; + } +#ifdef DEBUG_BLT24 + ErrorF ("\n"); +#endif +} +#endif /* FB_24BIT */ + +#if FB_SHIFT == FB_STIP_SHIFT + 1 + +/* + * Could be generalized to FB_SHIFT > FB_STIP_SHIFT + 1 by + * creating an ring of values stepped through for each line + */ + +void +fbBltOdd (FbBits *srcLine, + FbStride srcStrideEven, + FbStride srcStrideOdd, + int srcXEven, + int srcXOdd, + + FbBits *dstLine, + FbStride dstStrideEven, + FbStride dstStrideOdd, + int dstXEven, + int dstXOdd, + + int width, + int height, + + int alu, + FbBits pm, + int bpp) +{ + FbBits *src; + int leftShiftEven, rightShiftEven; + FbBits startmaskEven, endmaskEven; + int nmiddleEven; + + FbBits *dst; + int leftShiftOdd, rightShiftOdd; + FbBits startmaskOdd, endmaskOdd; + int nmiddleOdd; + + int leftShift, rightShift; + FbBits startmask, endmask; + int nmiddle; + + int srcX, dstX; + + FbBits bits, bits1; + int n; + + Bool destInvarient; + Bool even; + FbDeclareMergeRop (); + + FbInitializeMergeRop (alu, pm); + destInvarient = FbDestInvarientMergeRop(); + + srcLine += srcXEven >> FB_SHIFT; + dstLine += dstXEven >> FB_SHIFT; + srcXEven &= FB_MASK; + dstXEven &= FB_MASK; + srcXOdd &= FB_MASK; + dstXOdd &= FB_MASK; + + FbMaskBits(dstXEven, width, startmaskEven, nmiddleEven, endmaskEven); + FbMaskBits(dstXOdd, width, startmaskOdd, nmiddleOdd, endmaskOdd); + + even = TRUE; + InitializeShifts(srcXEven, dstXEven, leftShiftEven, rightShiftEven); + InitializeShifts(srcXOdd, dstXOdd, leftShiftOdd, rightShiftOdd); + while (height--) + { + src = srcLine; + dst = dstLine; + if (even) + { + srcX = srcXEven; + dstX = dstXEven; + startmask = startmaskEven; + endmask = endmaskEven; + nmiddle = nmiddleEven; + leftShift = leftShiftEven; + rightShift = rightShiftEven; + srcLine += srcStrideEven; + dstLine += dstStrideEven; + even = FALSE; + } + else + { + srcX = srcXOdd; + dstX = dstXOdd; + startmask = startmaskOdd; + endmask = endmaskOdd; + nmiddle = nmiddleOdd; + leftShift = leftShiftOdd; + rightShift = rightShiftOdd; + srcLine += srcStrideOdd; + dstLine += dstStrideOdd; + even = TRUE; + } + if (srcX == dstX) + { + if (startmask) + { + bits = *src++; + *dst = FbDoMaskMergeRop (bits, *dst, startmask); + dst++; + } + n = nmiddle; + if (destInvarient) + { + while (n--) + { + bits = *src++; + *dst = FbDoDestInvarientMergeRop(bits); + dst++; + } + } + else + { + while (n--) + { + bits = *src++; + *dst = FbDoMergeRop (bits, *dst); + dst++; + } + } + if (endmask) + { + bits = *src; + *dst = FbDoMaskMergeRop(bits, *dst, endmask); + } + } + else + { + bits = 0; + if (srcX > dstX) + bits = *src++; + if (startmask) + { + bits1 = FbScrLeft(bits, leftShift); + bits = *src++; + bits1 |= FbScrRight(bits, rightShift); + *dst = FbDoMaskMergeRop (bits1, *dst, startmask); + dst++; + } + n = nmiddle; + if (destInvarient) + { + while (n--) + { + bits1 = FbScrLeft(bits, leftShift); + bits = *src++; + bits1 |= FbScrRight(bits, rightShift); + *dst = FbDoDestInvarientMergeRop(bits1); + dst++; + } + } + else + { + while (n--) + { + bits1 = FbScrLeft(bits, leftShift); + bits = *src++; + bits1 |= FbScrRight(bits, rightShift); + *dst = FbDoMergeRop(bits1, *dst); + dst++; + } + } + if (endmask) + { + bits1 = FbScrLeft(bits, leftShift); + if (FbScrLeft(endmask, rightShift)) + { + bits = *src; + bits1 |= FbScrRight(bits, rightShift); + } + *dst = FbDoMaskMergeRop (bits1, *dst, endmask); + } + } + } +} + +#ifdef FB_24BIT +void +fbBltOdd24 (FbBits *srcLine, + FbStride srcStrideEven, + FbStride srcStrideOdd, + int srcXEven, + int srcXOdd, + + FbBits *dstLine, + FbStride dstStrideEven, + FbStride dstStrideOdd, + int dstXEven, + int dstXOdd, + + int width, + int height, + + int alu, + FbBits pm) +{ + Bool even = TRUE; + + while (height--) + { + if (even) + { + fbBlt24Line (srcLine, srcXEven, dstLine, dstXEven, + width, alu, pm, FALSE); + srcLine += srcStrideEven; + dstLine += dstStrideEven; + even = FALSE; + } + else + { + fbBlt24Line (srcLine, srcXOdd, dstLine, dstXOdd, + width, alu, pm, FALSE); + srcLine += srcStrideOdd; + dstLine += dstStrideOdd; + even = TRUE; + } + } +#if 0 + fprintf (stderr, "\n"); +#endif +} +#endif + +#endif + +#if FB_STIP_SHIFT != FB_SHIFT +void +fbSetBltOdd (FbStip *stip, + FbStride stipStride, + int srcX, + FbBits **bits, + FbStride *strideEven, + FbStride *strideOdd, + int *srcXEven, + int *srcXOdd) +{ + int srcAdjust; + int strideAdjust; + + /* + * bytes needed to align source + */ + srcAdjust = (((int) stip) & (FB_MASK >> 3)); + /* + * FbStip units needed to align stride + */ + strideAdjust = stipStride & (FB_MASK >> FB_STIP_SHIFT); + + *bits = (FbBits *) ((char *) stip - srcAdjust); + if (srcAdjust) + { + *strideEven = FbStipStrideToBitsStride (stipStride + 1); + *strideOdd = FbStipStrideToBitsStride (stipStride); + + *srcXEven = srcX + (srcAdjust << 3); + *srcXOdd = srcX + (srcAdjust << 3) - (strideAdjust << FB_STIP_SHIFT); + } + else + { + *strideEven = FbStipStrideToBitsStride (stipStride); + *strideOdd = FbStipStrideToBitsStride (stipStride + 1); + + *srcXEven = srcX; + *srcXOdd = srcX + (strideAdjust << FB_STIP_SHIFT); + } +} +#endif + +void +fbBltStip (FbStip *src, + FbStride srcStride, /* in FbStip units, not FbBits units */ + int srcX, + + FbStip *dst, + FbStride dstStride, /* in FbStip units, not FbBits units */ + int dstX, + + int width, + int height, + + int alu, + FbBits pm, + int bpp) +{ +#if FB_STIP_SHIFT != FB_SHIFT + if (FB_STIP_ODDSTRIDE(srcStride) || FB_STIP_ODDPTR(src) || + FB_STIP_ODDSTRIDE(dstStride) || FB_STIP_ODDPTR(dst)) + { + FbStride srcStrideEven, srcStrideOdd; + FbStride dstStrideEven, dstStrideOdd; + int srcXEven, srcXOdd; + int dstXEven, dstXOdd; + FbBits *s, *d; + int sx, dx; + + src += srcX >> FB_STIP_SHIFT; + srcX &= FB_STIP_MASK; + dst += dstX >> FB_STIP_SHIFT; + dstX &= FB_STIP_MASK; + + fbSetBltOdd (src, srcStride, srcX, + &s, + &srcStrideEven, &srcStrideOdd, + &srcXEven, &srcXOdd); + + fbSetBltOdd (dst, dstStride, dstX, + &d, + &dstStrideEven, &dstStrideOdd, + &dstXEven, &dstXOdd); + +#ifdef FB_24BIT + if (bpp == 24 && !FbCheck24Pix (pm)) + { + fbBltOdd24 (s, srcStrideEven, srcStrideOdd, + srcXEven, srcXOdd, + + d, dstStrideEven, dstStrideOdd, + dstXEven, dstXOdd, + + width, height, alu, pm); + } + else +#endif + { + fbBltOdd (s, srcStrideEven, srcStrideOdd, + srcXEven, srcXOdd, + + d, dstStrideEven, dstStrideOdd, + dstXEven, dstXOdd, + + width, height, alu, pm, bpp); + } + } + else +#endif + { + fbBlt ((FbBits *) src, FbStipStrideToBitsStride (srcStride), + srcX, + (FbBits *) dst, FbStipStrideToBitsStride (dstStride), + dstX, + width, height, + alu, pm, bpp, FALSE, FALSE); + } +} diff --git a/fb/fbbltone.c b/fb/fbbltone.c new file mode 100644 index 000000000..e758794b8 --- /dev/null +++ b/fb/fbbltone.c @@ -0,0 +1,865 @@ +/* + * Id: fbbltone.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbbltone.c,v 1.13 2002/02/23 00:42:07 keithp Exp $ */ + +#include "fb.h" + +/* + * Example: srcX = 13 dstX = 8 (FB unit 32 dstBpp 8) + * + * **** **** **** **** **** **** **** **** + * ^ + * ******** ******** ******** ******** + * ^ + * leftShift = 12 + * rightShift = 20 + * + * Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8) + * + * **** **** **** **** **** **** **** **** + * ^ + * ******** ******** ******** ******** + * ^ + * + * leftShift = 24 + * rightShift = 8 + */ + +#define LoadBits {\ + if (leftShift) { \ + bitsRight = *src++; \ + bits = (FbStipLeft (bitsLeft, leftShift) | \ + FbStipRight(bitsRight, rightShift)); \ + bitsLeft = bitsRight; \ + } else \ + bits = *src++; \ +} + +#ifndef FBNOPIXADDR + +#define LaneCases1(n,a) case n: (void)FbLaneCase(n,a); break +#define LaneCases2(n,a) LaneCases1(n,a); LaneCases1(n+1,a) +#define LaneCases4(n,a) LaneCases2(n,a); LaneCases2(n+2,a) +#define LaneCases8(n,a) LaneCases4(n,a); LaneCases4(n+4,a) +#define LaneCases16(n,a) LaneCases8(n,a); LaneCases8(n+8,a) +#define LaneCases32(n,a) LaneCases16(n,a); LaneCases16(n+16,a) +#define LaneCases64(n,a) LaneCases32(n,a); LaneCases32(n+32,a) +#define LaneCases128(n,a) LaneCases64(n,a); LaneCases64(n+64,a) +#define LaneCases256(n,a) LaneCases128(n,a); LaneCases128(n+128,a) + +#if FB_SHIFT == 6 +#define LaneCases(a) LaneCases256(0,a) +#endif + +#if FB_SHIFT == 5 +#define LaneCases(a) LaneCases16(0,a) +#endif + +#if FB_SHIFT == 6 +CARD8 fb8Lane[256] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, +22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, +41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, +60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, +79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, +98, 99, 100, 101, 102,103,104,105,106,107,108,109,110,111,112,113,114,115, +116, 117, 118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, +134, 135, 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, +152, 153, 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169, +170, 171, 172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187, +188, 189, 190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205, +206, 207, 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, +224, 225, 226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241, +242, 243, 244,245,246,247,248,249,250,251,252,253,254,255, +}; + +CARD8 fb16Lane[256] = { + 0x00, 0x03, 0x0c, 0x0f, + 0x30, 0x33, 0x3c, 0x3f, + 0xc0, 0xc3, 0xcc, 0xcf, + 0xf0, 0xf3, 0xfc, 0xff, +}; + +CARD8 fb32Lane[16] = { + 0x00, 0x0f, 0xf0, 0xff, +}; +#endif + +#if FB_SHIFT == 5 +CARD8 fb8Lane[16] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +CARD8 fb16Lane[16] = { + 0, 3, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +CARD8 fb32Lane[16] = { + 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +#endif + +CARD8 *fbLaneTable[33] = { + 0, 0, 0, 0, 0, 0, 0, 0, + fb8Lane, 0, 0, 0, 0, 0, 0, 0, + fb16Lane, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + fb32Lane +}; +#endif + +void +fbBltOne (FbStip *src, + FbStride srcStride, /* FbStip units per scanline */ + int srcX, /* bit position of source */ + FbBits *dst, + FbStride dstStride, /* FbBits units per scanline */ + int dstX, /* bit position of dest */ + int dstBpp, /* bits per destination unit */ + + int width, /* width in bits of destination */ + int height, /* height in scanlines */ + + FbBits fgand, /* rrop values */ + FbBits fgxor, + FbBits bgand, + FbBits bgxor) +{ + const FbBits *fbBits; + int pixelsPerDst; /* dst pixels per FbBits */ + int unitsPerSrc; /* src patterns per FbStip */ + int leftShift, rightShift; /* align source with dest */ + FbBits startmask, endmask; /* dest scanline masks */ + FbStip bits=0, bitsLeft, bitsRight;/* source bits */ + FbStip left; + FbBits mask; + int nDst; /* dest longwords (w.o. end) */ + int w; + int n, nmiddle; + int dstS; /* stipple-relative dst X coordinate */ + Bool copy; /* accelerate dest-invariant */ + Bool transparent; /* accelerate 0 nop */ + int srcinc; /* source units consumed */ + Bool endNeedsLoad = FALSE; /* need load for endmask */ +#ifndef FBNOPIXADDR + CARD8 *fbLane; +#endif + int startbyte, endbyte; + +#ifdef FB_24BIT + if (dstBpp == 24) + { + fbBltOne24 (src, srcStride, srcX, + dst, dstStride, dstX, dstBpp, + width, height, + fgand, fgxor, bgand, bgxor); + return; + } +#endif + + /* + * Number of destination units in FbBits == number of stipple pixels + * used each time + */ + pixelsPerDst = FB_UNIT / dstBpp; + + /* + * Number of source stipple patterns in FbStip + */ + unitsPerSrc = FB_STIP_UNIT / pixelsPerDst; + + copy = FALSE; + transparent = FALSE; + if (bgand == 0 && fgand == 0) + copy = TRUE; + else if (bgand == FB_ALLONES && bgxor == 0) + transparent = TRUE; + + /* + * Adjust source and dest to nearest FbBits boundary + */ + src += srcX >> FB_STIP_SHIFT; + dst += dstX >> FB_SHIFT; + srcX &= FB_STIP_MASK; + dstX &= FB_MASK; + + FbMaskBitsBytes(dstX, width, copy, + startmask, startbyte, nmiddle, endmask, endbyte); + + /* + * Compute effective dest alignment requirement for + * source -- must align source to dest unit boundary + */ + dstS = dstX / dstBpp; + /* + * Compute shift constants for effective alignement + */ + if (srcX >= dstS) + { + leftShift = srcX - dstS; + rightShift = FB_STIP_UNIT - leftShift; + } + else + { + rightShift = dstS - srcX; + leftShift = FB_STIP_UNIT - rightShift; + } + /* + * Get pointer to stipple mask array for this depth + */ + fbBits = 0; /* unused */ + if (pixelsPerDst <= 8) + fbBits = fbStippleTable[pixelsPerDst]; +#ifndef FBNOPIXADDR + fbLane = 0; + if (transparent && fgand == 0 && dstBpp >= 8) + fbLane = fbLaneTable[dstBpp]; +#endif + + /* + * Compute total number of destination words written, but + * don't count endmask + */ + nDst = nmiddle; + if (startmask) + nDst++; + + dstStride -= nDst; + + /* + * Compute total number of source words consumed + */ + + srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc; + + if (srcX > dstS) + srcinc++; + if (endmask) + { + endNeedsLoad = nDst % unitsPerSrc == 0; + if (endNeedsLoad) + srcinc++; + } + + srcStride -= srcinc; + + /* + * Copy rectangle + */ + while (height--) + { + w = nDst; /* total units across scanline */ + n = unitsPerSrc; /* units avail in single stipple */ + if (n > w) + n = w; + + bitsLeft = 0; + if (srcX > dstS) + bitsLeft = *src++; + if (n) + { + /* + * Load first set of stipple bits + */ + LoadBits; + + /* + * Consume stipple bits for startmask + */ + if (startmask) + { +#if FB_UNIT > 32 + if (pixelsPerDst == 16) + mask = FbStipple16Bits(FbLeftStipBits(bits,16)); + else +#endif + mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; +#ifndef FBNOPIXADDR + if (fbLane) + { + fbTransparentSpan (dst, mask & startmask, fgxor, 1); + } + else +#endif + { + if (mask || !transparent) + FbDoLeftMaskByteStippleRRop (dst, mask, + fgand, fgxor, bgand, bgxor, + startbyte, startmask); + } + bits = FbStipLeft (bits, pixelsPerDst); + dst++; + n--; + w--; + } + /* + * Consume stipple bits across scanline + */ + for (;;) + { + w -= n; + if (copy) + { + while (n--) + { +#if FB_UNIT > 32 + if (pixelsPerDst == 16) + mask = FbStipple16Bits(FbLeftStipBits(bits,16)); + else +#endif + mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; + *dst = FbOpaqueStipple (mask, fgxor, bgxor); + dst++; + bits = FbStipLeft(bits, pixelsPerDst); + } + } + else + { +#ifndef FBNOPIXADDR + if (fbLane) + { + while (bits && n) + { + switch (fbLane[FbLeftStipBits(bits,pixelsPerDst)]) { + LaneCases((CARD8 *) dst); + } + bits = FbStipLeft(bits,pixelsPerDst); + dst++; + n--; + } + dst += n; + } + else +#endif + { + while (n--) + { + left = FbLeftStipBits(bits,pixelsPerDst); + if (left || !transparent) + { + mask = fbBits[left]; + *dst = FbStippleRRop (*dst, mask, + fgand, fgxor, bgand, bgxor); + } + dst++; + bits = FbStipLeft(bits, pixelsPerDst); + } + } + } + if (!w) + break; + /* + * Load another set and reset number of available units + */ + LoadBits; + n = unitsPerSrc; + if (n > w) + n = w; + } + } + /* + * Consume stipple bits for endmask + */ + if (endmask) + { + if (endNeedsLoad) + { + LoadBits; + } +#if FB_UNIT > 32 + if (pixelsPerDst == 16) + mask = FbStipple16Bits(FbLeftStipBits(bits,16)); + else +#endif + mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; +#ifndef FBNOPIXADDR + if (fbLane) + { + fbTransparentSpan (dst, mask & endmask, fgxor, 1); + } + else +#endif + { + if (mask || !transparent) + FbDoRightMaskByteStippleRRop (dst, mask, + fgand, fgxor, bgand, bgxor, + endbyte, endmask); + } + } + dst += dstStride; + src += srcStride; + } +} + +#ifdef FB_24BIT + +/* + * Crufty macros to initialize the mask array, most of this + * is to avoid compile-time warnings about shift overflow + */ + +#if BITMAP_BIT_ORDER == MSBFirst +#define Mask24Pos(x,r) ((x)*24-(r)) +#else +#define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0)) +#endif + +#define Mask24Neg(x,r) (Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0) +#define Mask24Check(x,r) (Mask24Pos(x,r) < 0 ? 0 : \ + Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r)) + +#define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \ + (Mask24Pos(x,r) < 0 ? \ + 0xffffff >> Mask24Neg (x,r) : \ + 0xffffff << Mask24Check(x,r)) : 0) + +#define SelMask24(b,n,r) ((((b) >> n) & 1) * Mask24(n,r)) + +/* + * Untested for MSBFirst or FB_UNIT == 32 + */ + +#if FB_UNIT == 64 +#define C4_24(b,r) \ + (SelMask24(b,0,r) | \ + SelMask24(b,1,r) | \ + SelMask24(b,2,r) | \ + SelMask24(b,3,r)) + +#define FbStip24New(rot) (2 + (rot != 0)) +#define FbStip24Len 4 + +const FbBits fbStipple24Bits[3][1 << FbStip24Len] = { + /* rotate 0 */ + { + C4_24( 0, 0), C4_24( 1, 0), C4_24( 2, 0), C4_24( 3, 0), + C4_24( 4, 0), C4_24( 5, 0), C4_24( 6, 0), C4_24( 7, 0), + C4_24( 8, 0), C4_24( 9, 0), C4_24(10, 0), C4_24(11, 0), + C4_24(12, 0), C4_24(13, 0), C4_24(14, 0), C4_24(15, 0), + }, + /* rotate 8 */ + { + C4_24( 0, 8), C4_24( 1, 8), C4_24( 2, 8), C4_24( 3, 8), + C4_24( 4, 8), C4_24( 5, 8), C4_24( 6, 8), C4_24( 7, 8), + C4_24( 8, 8), C4_24( 9, 8), C4_24(10, 8), C4_24(11, 8), + C4_24(12, 8), C4_24(13, 8), C4_24(14, 8), C4_24(15, 8), + }, + /* rotate 16 */ + { + C4_24( 0,16), C4_24( 1,16), C4_24( 2,16), C4_24( 3,16), + C4_24( 4,16), C4_24( 5,16), C4_24( 6,16), C4_24( 7,16), + C4_24( 8,16), C4_24( 9,16), C4_24(10,16), C4_24(11,16), + C4_24(12,16), C4_24(13,16), C4_24(14,16), C4_24(15,16), + } +}; + +#endif + +#if FB_UNIT == 32 +#define C2_24(b,r) \ + (SelMask24(b,0,r) | \ + SelMask24(b,1,r)) + +#define FbStip24Len 2 +#if BITMAP_BIT_ORDER == MSBFirst +#define FbStip24New(rot) (1 + (rot == 0)) +#else +#define FbStip24New(rot) (1 + (rot == 8)) +#endif + +const FbBits fbStipple24Bits[3][1 << FbStip24Len] = { + /* rotate 0 */ + { + C2_24( 0, 0), C2_24 ( 1, 0), C2_24 ( 2, 0), C2_24 ( 3, 0), + }, + /* rotate 8 */ + { + C2_24( 0, 8), C2_24 ( 1, 8), C2_24 ( 2, 8), C2_24 ( 3, 8), + }, + /* rotate 16 */ + { + C2_24( 0,16), C2_24 ( 1,16), C2_24 ( 2,16), C2_24 ( 3,16), + } +}; +#endif + +#if BITMAP_BIT_ORDER == LSBFirst + +#define FbMergeStip24Bits(left, right, new) \ + (FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new)))) + +#define FbMergePartStip24Bits(left, right, llen, rlen) \ + (left | FbStipRight(right, llen)) + +#else + +#define FbMergeStip24Bits(left, right, new) \ + ((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right) + +#define FbMergePartStip24Bits(left, right, llen, rlen) \ + (FbStipLeft(left, rlen) | right) + +#endif + +#define fbFirstStipBits(len,stip) {\ + int __len = (len); \ + if (len <= remain) { \ + stip = FbLeftStipBits(bits, len); \ + } else { \ + stip = FbLeftStipBits(bits, remain); \ + bits = *src++; \ + __len = (len) - remain; \ + stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \ + remain, __len); \ + remain = FB_STIP_UNIT; \ + } \ + bits = FbStipLeft (bits, __len); \ + remain -= __len; \ +} + +#define fbInitStipBits(offset,len,stip) {\ + bits = FbStipLeft (*src++,offset); \ + remain = FB_STIP_UNIT - offset; \ + fbFirstStipBits(len,stip); \ + stip = FbMergeStip24Bits (0, stip, len); \ +} + +#define fbNextStipBits(rot,stip) {\ + int __new = FbStip24New(rot); \ + FbStip __right; \ + fbFirstStipBits(__new, __right); \ + stip = FbMergeStip24Bits (stip, __right, __new); \ + rot = FbNext24Rot (rot); \ +} + +/* + * Use deep mask tables that incorporate rotation, pull + * a variable number of bits out of the stipple and + * reuse the right bits as needed for the next write + * + * Yes, this is probably too much code, but most 24-bpp screens + * have no acceleration so this code is used for stipples, copyplane + * and text + */ +void +fbBltOne24 (FbStip *srcLine, + FbStride srcStride, /* FbStip units per scanline */ + int srcX, /* bit position of source */ + FbBits *dst, + FbStride dstStride, /* FbBits units per scanline */ + int dstX, /* bit position of dest */ + int dstBpp, /* bits per destination unit */ + + int width, /* width in bits of destination */ + int height, /* height in scanlines */ + + FbBits fgand, /* rrop values */ + FbBits fgxor, + FbBits bgand, + FbBits bgxor) +{ + FbStip *src; + FbBits leftMask, rightMask, mask; + int nlMiddle, nl; + FbStip stip, bits; + int remain; + int dstS; + int firstlen; + int rot0, rot; + int nDst; + + srcLine += srcX >> FB_STIP_SHIFT; + dst += dstX >> FB_SHIFT; + srcX &= FB_STIP_MASK; + dstX &= FB_MASK; + rot0 = FbFirst24Rot (dstX); + + FbMaskBits (dstX, width, leftMask, nlMiddle, rightMask); + + dstS = (dstX + 23) / 24; + firstlen = FbStip24Len - dstS; + + nDst = nlMiddle; + if (leftMask) + nDst++; + dstStride -= nDst; + + /* opaque copy */ + if (bgand == 0 && fgand == 0) + { + while (height--) + { + rot = rot0; + src = srcLine; + srcLine += srcStride; + fbInitStipBits (srcX,firstlen, stip); + if (leftMask) + { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = (*dst & ~leftMask) | (FbOpaqueStipple (mask, + FbRot24(fgxor, rot), + FbRot24(bgxor, rot)) + & leftMask); + dst++; + fbNextStipBits(rot,stip); + } + nl = nlMiddle; + while (nl--) + { + mask = fbStipple24Bits[rot>>3][stip]; + *dst = FbOpaqueStipple (mask, + FbRot24(fgxor, rot), + FbRot24(bgxor, rot)); + dst++; + fbNextStipBits(rot,stip); + } + if (rightMask) + { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = (*dst & ~rightMask) | (FbOpaqueStipple (mask, + FbRot24(fgxor, rot), + FbRot24(bgxor, rot)) + & rightMask); + } + dst += dstStride; + src += srcStride; + } + } + /* transparent copy */ + else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0) + { + while (height--) + { + rot = rot0; + src = srcLine; + srcLine += srcStride; + fbInitStipBits (srcX, firstlen, stip); + if (leftMask) + { + if (stip) + { + mask = fbStipple24Bits[rot >> 3][stip] & leftMask; + *dst = (*dst & ~mask) | (FbRot24(fgxor, rot) & mask); + } + dst++; + fbNextStipBits (rot, stip); + } + nl = nlMiddle; + while (nl--) + { + if (stip) + { + mask = fbStipple24Bits[rot>>3][stip]; + *dst = (*dst & ~mask) | (FbRot24(fgxor,rot) & mask); + } + dst++; + fbNextStipBits (rot, stip); + } + if (rightMask) + { + if (stip) + { + mask = fbStipple24Bits[rot >> 3][stip] & rightMask; + *dst = (*dst & ~mask) | (FbRot24(fgxor, rot) & mask); + } + } + dst += dstStride; + } + } + else + { + while (height--) + { + rot = rot0; + src = srcLine; + srcLine += srcStride; + fbInitStipBits (srcX, firstlen, stip); + if (leftMask) + { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = FbStippleRRopMask (*dst, mask, + FbRot24(fgand, rot), + FbRot24(fgxor, rot), + FbRot24(bgand, rot), + FbRot24(bgxor, rot), + leftMask); + dst++; + fbNextStipBits(rot,stip); + } + nl = nlMiddle; + while (nl--) + { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = FbStippleRRop (*dst, mask, + FbRot24(fgand, rot), + FbRot24(fgxor, rot), + FbRot24(bgand, rot), + FbRot24(bgxor, rot)); + dst++; + fbNextStipBits(rot,stip); + } + if (rightMask) + { + mask = fbStipple24Bits[rot >> 3][stip]; + *dst = FbStippleRRopMask (*dst, mask, + FbRot24(fgand, rot), + FbRot24(fgxor, rot), + FbRot24(bgand, rot), + FbRot24(bgxor, rot), + rightMask); + } + dst += dstStride; + } + } +} +#endif + +/* + * Not very efficient, but simple -- copy a single plane + * from an N bit image to a 1 bit image + */ + +void +fbBltPlane (FbBits *src, + FbStride srcStride, + int srcX, + int srcBpp, + + FbStip *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + FbStip fgand, + FbStip fgxor, + FbStip bgand, + FbStip bgxor, + Pixel planeMask) +{ + FbBits *s; + FbBits pm; + FbBits srcMask; + FbBits srcMaskFirst; + FbBits srcMask0 = 0; + FbBits srcBits; + + FbStip dstBits; + FbStip *d; + FbStip dstMask; + FbStip dstMaskFirst; + FbStip dstUnion; + int w; + int wt; + int rot0; + + if (!width) + return; + + src += srcX >> FB_SHIFT; + srcX &= FB_MASK; + + dst += dstX >> FB_STIP_SHIFT; + dstX &= FB_STIP_MASK; + + w = width / srcBpp; + + pm = fbReplicatePixel (planeMask, srcBpp); +#ifdef FB_24BIT + if (srcBpp == 24) + { + int w = 24; + + rot0 = FbFirst24Rot (srcX); + if (srcX + w > FB_UNIT) + w = FB_UNIT - srcX; + srcMaskFirst = FbRot24(pm,rot0) & FbBitsMask(srcX,w); + } + else +#endif + { + rot0 = 0; + srcMaskFirst = pm & FbBitsMask(srcX, srcBpp); + srcMask0 = pm & FbBitsMask(0, srcBpp); + } + + dstMaskFirst = FbStipMask(dstX,1); + while (height--) + { + d = dst; + dst += dstStride; + s = src; + src += srcStride; + + srcMask = srcMaskFirst; +#ifdef FB_24BIT + if (srcBpp == 24) + srcMask0 = FbRot24(pm,rot0) & FbBitsMask(0, srcBpp); +#endif + srcBits = *s++; + + dstMask = dstMaskFirst; + dstUnion = 0; + dstBits = 0; + + wt = w; + + while (wt--) + { + if (!srcMask) + { + srcBits = *s++; +#ifdef FB_24BIT + if (srcBpp == 24) + srcMask0 = FbNext24Pix(srcMask0) & FbBitsMask(0,24); +#endif + srcMask = srcMask0; + } + if (!dstMask) + { + *d = FbStippleRRopMask(*d, dstBits, + fgand, fgxor, bgand, bgxor, + dstUnion); + d++; + dstMask = FbStipMask(0,1); + dstUnion = 0; + dstBits = 0; + } + if (srcBits & srcMask) + dstBits |= dstMask; + dstUnion |= dstMask; + if (srcBpp == FB_UNIT) + srcMask = 0; + else + srcMask = FbScrRight(srcMask,srcBpp); + dstMask = FbStipRight(dstMask,1); + } + if (dstUnion) + *d = FbStippleRRopMask(*d,dstBits, + fgand, fgxor, bgand, bgxor, + dstUnion); + } +} + diff --git a/fb/fbbstore.c b/fb/fbbstore.c new file mode 100644 index 000000000..07a6400a8 --- /dev/null +++ b/fb/fbbstore.c @@ -0,0 +1,62 @@ +/* + * Id: fbbstore.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbbstore.c,v 1.2 2000/02/23 20:29:42 dawes Exp $ */ + +#include "fb.h" + +void +fbSaveAreas(PixmapPtr pPixmap, + RegionPtr prgnSave, + int xorg, + int yorg, + WindowPtr pWin) +{ + fbCopyWindowProc (&pWin->drawable, + &pPixmap->drawable, + 0, + REGION_RECTS(prgnSave), + REGION_NUM_RECTS(prgnSave), + xorg, yorg, + FALSE, + FALSE, + 0,0); +} + +void +fbRestoreAreas(PixmapPtr pPixmap, + RegionPtr prgnRestore, + int xorg, + int yorg, + WindowPtr pWin) +{ + fbCopyWindowProc (&pPixmap->drawable, + &pWin->drawable, + 0, + REGION_RECTS(prgnRestore), + REGION_NUM_RECTS(prgnRestore), + -xorg, -yorg, + FALSE, + FALSE, + 0,0); +} diff --git a/fb/fbcmap.c b/fb/fbcmap.c new file mode 100644 index 000000000..aeb53b1fb --- /dev/null +++ b/fb/fbcmap.c @@ -0,0 +1,668 @@ +/* $XConsortium: fbcmap.c,v 4.19 94/04/17 20:28:46 dpw Exp $ */ +/* $XFree86: xc/programs/Xserver/fb/fbcmap.c,v 1.6 2001/10/28 03:33:08 tsi Exp $ */ +/************************************************************ +Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright no- +tice appear in all copies and that both that copyright no- +tice and this permission notice appear in supporting docu- +mentation, and that the names of Sun or X Consortium +not be used in advertising or publicity pertaining to +distribution of the software without specific prior +written permission. Sun and X Consortium make no +representations about the suitability of this software for +any purpose. It is provided "as is" without any express or +implied warranty. + +SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- +NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- +ABLE 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. + +********************************************************/ + + +#include "X.h" +#include "Xproto.h" +#include "scrnintstr.h" +#include "colormapst.h" +#include "resource.h" +#include "fb.h" + +#ifndef XFree86Server +ColormapPtr FbInstalledMaps[MAXSCREENS]; + +int +fbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) +{ + /* By the time we are processing requests, we can guarantee that there + * is always a colormap installed */ + *pmaps = FbInstalledMaps[pScreen->myNum]->mid; + return (1); +} + + +void +fbInstallColormap(ColormapPtr pmap) +{ + int index = pmap->pScreen->myNum; + ColormapPtr oldpmap = FbInstalledMaps[index]; + + if(pmap != oldpmap) + { + /* Uninstall pInstalledMap. No hardware changes required, just + * notify all interested parties. */ + if(oldpmap != (ColormapPtr)None) + WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); + /* Install pmap */ + FbInstalledMaps[index] = pmap; + WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); + } +} + +void +fbUninstallColormap(ColormapPtr pmap) +{ + int index = pmap->pScreen->myNum; + ColormapPtr curpmap = FbInstalledMaps[index]; + + if(pmap == curpmap) + { + if (pmap->mid != pmap->pScreen->defColormap) + { + curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, + RT_COLORMAP); + (*pmap->pScreen->InstallColormap)(curpmap); + } + } +} + +void +fbResolveColor(unsigned short *pred, + unsigned short *pgreen, + unsigned short *pblue, + VisualPtr pVisual) +{ + int shift = 16 - pVisual->bitsPerRGBValue; + unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1; + + if ((pVisual->class | DynamicClass) == GrayScale) + { + /* rescale to gray then rgb bits */ + *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100; + *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim; + } + else + { + /* rescale to rgb bits */ + *pred = ((*pred >> shift) * 65535) / lim; + *pgreen = ((*pgreen >> shift) * 65535) / lim; + *pblue = ((*pblue >> shift) * 65535) / lim; + } +} + +Bool +fbInitializeColormap(ColormapPtr pmap) +{ + register unsigned i; + register VisualPtr pVisual; + unsigned lim, maxent, shift; + + pVisual = pmap->pVisual; + lim = (1 << pVisual->bitsPerRGBValue) - 1; + shift = 16 - pVisual->bitsPerRGBValue; + maxent = pVisual->ColormapEntries - 1; + if (pVisual->class == TrueColor) + { + unsigned limr, limg, limb; + + limr = pVisual->redMask >> pVisual->offsetRed; + limg = pVisual->greenMask >> pVisual->offsetGreen; + limb = pVisual->blueMask >> pVisual->offsetBlue; + for(i = 0; i <= maxent; i++) + { + /* rescale to [0..65535] then rgb bits */ + pmap->red[i].co.local.red = + ((((i * 65535) / limr) >> shift) * 65535) / lim; + pmap->green[i].co.local.green = + ((((i * 65535) / limg) >> shift) * 65535) / lim; + pmap->blue[i].co.local.blue = + ((((i * 65535) / limb) >> shift) * 65535) / lim; + } + } + else if (pVisual->class == StaticColor) + { + unsigned n; + unsigned r, g, b; + unsigned red, green, blue; + + for (n = 0; n*n*n < pVisual->ColormapEntries; n++) + ; + n--; + i = 0; + for (r = 0; r < n; r++) + { + red = (((r * 65535 / (n - 1)) >> shift) * 65535) / lim; + for (g = 0; g < n; g++) + { + green = (((g * 65535 / (n - 1)) >> shift) * 65535) / lim; + for (b = 0; b < n; b++) + { + blue = (((b * 65535 / (n - 1)) >> shift) * 65535) / lim; + pmap->red[i].co.local.red = red; + pmap->red[i].co.local.green = green; + pmap->red[i].co.local.blue = blue; + i++; + } + } + } + n = pVisual->ColormapEntries - i; + for (r = 0; r < n; r++) + { + red = (((r * 65535 / (n - 1)) >> shift) * 65535) / lim; + pmap->red[i].co.local.red = red; + pmap->red[i].co.local.green = red; + pmap->red[i].co.local.blue = red; + i++; + } + } + else if (pVisual->class == StaticGray) + { + for(i = 0; i <= maxent; i++) + { + /* rescale to [0..65535] then rgb bits */ + pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift) + * 65535) / lim; + pmap->red[i].co.local.green = pmap->red[i].co.local.red; + pmap->red[i].co.local.blue = pmap->red[i].co.local.red; + } + } + return TRUE; +} + +/* When simulating DirectColor on PseudoColor hardware, multiple + entries of the colormap must be updated + */ + +#define AddElement(mask) { \ + pixel = red | green | blue; \ + for (i = 0; i < nresult; i++) \ + if (outdefs[i].pixel == pixel) \ + break; \ + if (i == nresult) \ + { \ + nresult++; \ + outdefs[i].pixel = pixel; \ + outdefs[i].flags = 0; \ + } \ + outdefs[i].flags |= (mask); \ + outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \ + outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \ + outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \ +} + +int +fbExpandDirectColors (ColormapPtr pmap, + int ndef, + xColorItem *indefs, + xColorItem *outdefs) +{ + register int red, green, blue; + int maxred, maxgreen, maxblue; + int stepred, stepgreen, stepblue; + VisualPtr pVisual; + register int pixel; + register int nresult; + register int i; + + pVisual = pmap->pVisual; + + stepred = 1 << pVisual->offsetRed; + stepgreen = 1 << pVisual->offsetGreen; + stepblue = 1 << pVisual->offsetBlue; + maxred = pVisual->redMask; + maxgreen = pVisual->greenMask; + maxblue = pVisual->blueMask; + nresult = 0; + for (;ndef--; indefs++) + { + if (indefs->flags & DoRed) + { + red = indefs->pixel & pVisual->redMask; + for (green = 0; green <= maxgreen; green += stepgreen) + { + for (blue = 0; blue <= maxblue; blue += stepblue) + { + AddElement (DoRed) + } + } + } + if (indefs->flags & DoGreen) + { + green = indefs->pixel & pVisual->greenMask; + for (red = 0; red <= maxred; red += stepred) + { + for (blue = 0; blue <= maxblue; blue += stepblue) + { + AddElement (DoGreen) + } + } + } + if (indefs->flags & DoBlue) + { + blue = indefs->pixel & pVisual->blueMask; + for (red = 0; red <= maxred; red += stepred) + { + for (green = 0; green <= maxgreen; green += stepgreen) + { + AddElement (DoBlue) + } + } + } + } + return nresult; +} + +Bool +fbCreateDefColormap(ScreenPtr pScreen) +{ + unsigned short zero = 0, ones = 0xFFFF; + VisualPtr pVisual; + ColormapPtr cmap; + Pixel wp, bp; + + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++) + ; + + if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap, + (pVisual->class & DynamicClass) ? AllocNone : AllocAll, + 0) + != Success) + return FALSE; + wp = pScreen->whitePixel; + bp = pScreen->blackPixel; + if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) != + Success) || + (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) != + Success)) + return FALSE; + pScreen->whitePixel = wp; + pScreen->blackPixel = bp; + (*pScreen->InstallColormap)(cmap); + return TRUE; +} + +extern int defaultColorVisualClass; + +#define _RZ(d) ((d + 2) / 3) +#define _RS(d) 0 +#define _RM(d) ((1 << _RZ(d)) - 1) +#define _GZ(d) ((d - _RZ(d) + 1) / 2) +#define _GS(d) _RZ(d) +#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d)) +#define _BZ(d) (d - _RZ(d) - _GZ(d)) +#define _BS(d) (_RZ(d) + _GZ(d)) +#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d)) +#define _CE(d) (1 << _RZ(d)) + +#define MAX_PSEUDO_DEPTH 10 /* largest DAC size I know */ + +#define StaticGrayMask (1 << StaticGray) +#define GrayScaleMask (1 << GrayScale) +#define StaticColorMask (1 << StaticColor) +#define PseudoColorMask (1 << PseudoColor) +#define TrueColorMask (1 << TrueColor) +#define DirectColorMask (1 << DirectColor) + +#define ALL_VISUALS (StaticGrayMask|\ + GrayScaleMask|\ + StaticColorMask|\ + PseudoColorMask|\ + TrueColorMask|\ + DirectColorMask) + +#define LARGE_VISUALS (TrueColorMask|\ + DirectColorMask) + +typedef struct _fbVisuals { + struct _fbVisuals *next; + int depth; + int bitsPerRGB; + int visuals; + int count; + Pixel redMask, greenMask, blueMask; +} fbVisualsRec, *fbVisualsPtr; + +static const int fbVisualPriority[] = { + PseudoColor, DirectColor, GrayScale, StaticColor, TrueColor, StaticGray +}; + +#define NUM_PRIORITY 6 + +static fbVisualsPtr fbVisuals; + +static int +popCount (int i) +{ + int count; + + count = (i >> 1) & 033333333333; + count = i - count - ((count >> 1) & 033333333333); + count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */ + return count; +} + +/* + * Distance to least significant one bit + */ +static int +maskShift (Pixel p) +{ + int s; + + if (!p) return 0; + s = 0; + while (!(p & 1)) + { + s++; + p >>= 1; + } + return s; +} + +Bool +fbSetVisualTypesAndMasks (int depth, int visuals, int bitsPerRGB, + Pixel redMask, Pixel greenMask, Pixel blueMask) +{ + fbVisualsPtr new, *prev, v; + + new = (fbVisualsPtr) xalloc (sizeof *new); + if (!new) + return FALSE; + if (!redMask || !greenMask || !blueMask) + { + redMask = _RM(depth); + greenMask = _GM(depth); + blueMask = _BM(depth); + } + new->next = 0; + new->depth = depth; + new->visuals = visuals; + new->bitsPerRGB = bitsPerRGB; + new->redMask = redMask; + new->greenMask = greenMask; + new->blueMask = blueMask; + new->count = popCount (visuals); + for (prev = &fbVisuals; (v = *prev); prev = &v->next); + *prev = new; + return TRUE; +} + +Bool +fbHasVisualTypes (int depth) +{ + fbVisualsPtr v; + + for (v = fbVisuals; v; v = v->next) + if (v->depth == depth) + return TRUE; + return FALSE; +} + +Bool +fbSetVisualTypes (int depth, int visuals, int bitsPerRGB) +{ + return fbSetVisualTypesAndMasks (depth, visuals, bitsPerRGB, + _RM(depth), _GM(depth), _BM(depth)); +} + +/* + * Given a list of formats for a screen, create a list + * of visuals and depths for the screen which coorespond to + * the set which can be used with this version of fb. + */ + +Bool +fbInitVisuals (VisualPtr *visualp, + DepthPtr *depthp, + int *nvisualp, + int *ndepthp, + int *rootDepthp, + VisualID *defaultVisp, + unsigned long sizes, + int bitsPerRGB) +{ + int i, j = 0, k; + VisualPtr visual; + DepthPtr depth; + VisualID *vid; + int d, b; + int f; + int ndepth, nvisual; + int nvtype; + int vtype; + fbVisualsPtr visuals, nextVisuals; + + /* none specified, we'll guess from pixmap formats */ + if (!fbVisuals) + { + for (f = 0; f < screenInfo.numPixmapFormats; f++) + { + d = screenInfo.formats[f].depth; + b = screenInfo.formats[f].bitsPerPixel; + if (sizes & (1 << (b - 1))) + { + if (d > MAX_PSEUDO_DEPTH) + vtype = LARGE_VISUALS; + else if (d == 1) + vtype = StaticGrayMask; + else + vtype = ALL_VISUALS; + } + else + vtype = 0; + if (!fbSetVisualTypes (d, vtype, bitsPerRGB)) + return FALSE; + } + } + nvisual = 0; + ndepth = 0; + for (visuals = fbVisuals; visuals; visuals = nextVisuals) + { + nextVisuals = visuals->next; + ndepth++; + nvisual += visuals->count; + } + depth = (DepthPtr) xalloc (ndepth * sizeof (DepthRec)); + visual = (VisualPtr) xalloc (nvisual * sizeof (VisualRec)); + if (!depth || !visual) + { + xfree (depth); + xfree (visual); + return FALSE; + } + *depthp = depth; + *visualp = visual; + *ndepthp = ndepth; + *nvisualp = nvisual; + for (visuals = fbVisuals; visuals; visuals = nextVisuals) + { + nextVisuals = visuals->next; + d = visuals->depth; + vtype = visuals->visuals; + nvtype = visuals->count; + vid = NULL; + if (nvtype) + { + vid = (VisualID *) xalloc (nvtype * sizeof (VisualID)); + if (!vid) + return FALSE; + } + depth->depth = d; + depth->numVids = nvtype; + depth->vids = vid; + depth++; + for (i = 0; i < NUM_PRIORITY; i++) { + if (! (vtype & (1 << fbVisualPriority[i]))) + continue; + visual->class = fbVisualPriority[i]; + visual->bitsPerRGBValue = visuals->bitsPerRGB; + visual->ColormapEntries = 1 << d; + visual->nplanes = d; + visual->vid = *vid = FakeClientID (0); + switch (visual->class) { + case PseudoColor: + case GrayScale: + case StaticGray: + case StaticColor: + visual->redMask = 0; + visual->greenMask = 0; + visual->blueMask = 0; + visual->offsetRed = 0; + visual->offsetGreen = 0; + visual->offsetBlue = 0; + break; + case DirectColor: + case TrueColor: + visual->ColormapEntries = _CE(d); + visual->redMask = visuals->redMask; + visual->greenMask = visuals->greenMask; + visual->blueMask = visuals->blueMask; + visual->offsetRed = maskShift (visuals->redMask); + visual->offsetGreen = maskShift (visuals->greenMask); + visual->offsetBlue = maskShift (visuals->blueMask); + } + vid++; + visual++; + } + xfree (visuals); + } + fbVisuals = NULL; + visual = *visualp; + depth = *depthp; + for (i = 0; i < ndepth; i++) + { + if (*rootDepthp && *rootDepthp != depth[i].depth) + continue; + for (j = 0; j < depth[i].numVids; j++) + { + for (k = 0; k < nvisual; k++) + if (visual[k].vid == depth[i].vids[j]) + break; + if (k == nvisual) + continue; + if (defaultColorVisualClass < 0 || + visual[k].class == defaultColorVisualClass) + break; + } + if (j != depth[i].numVids) + break; + } + if (i == ndepth) { + for (i = 0; i < ndepth; i++) + { + if (depth[i].numVids) + break; + } + if (i == ndepth) + return FALSE; + j = 0; + } + *rootDepthp = depth[i].depth; + *defaultVisp = depth[i].vids[j]; + return TRUE; +} +#else + +#include "micmap.h" + +int +fbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) +{ + return miListInstalledColormaps(pScreen, pmaps); +} + +void +fbInstallColormap(ColormapPtr pmap) +{ + miInstallColormap(pmap); +} + +void +fbUninstallColormap(ColormapPtr pmap) +{ + miUninstallColormap(pmap); +} + +void +fbResolveColor(unsigned short *pred, + unsigned short *pgreen, + unsigned short *pblue, + VisualPtr pVisual) +{ + miResolveColor(pred, pgreen, pblue, pVisual); +} + +Bool +fbInitializeColormap(ColormapPtr pmap) +{ + return miInitializeColormap(pmap); +} + +int +fbExpandDirectColors (ColormapPtr pmap, + int ndef, + xColorItem *indefs, + xColorItem *outdefs) +{ + return miExpandDirectColors(pmap, ndef, indefs, outdefs); +} + +Bool +fbCreateDefColormap(ScreenPtr pScreen) +{ + return miCreateDefColormap(pScreen); +} + +void +fbClearVisualTypes(void) +{ + miClearVisualTypes(); +} + +Bool +fbSetVisualTypes (int depth, int visuals, int bitsPerRGB) +{ + return miSetVisualTypes(depth, visuals, bitsPerRGB, -1); +} + +/* + * Given a list of formats for a screen, create a list + * of visuals and depths for the screen which coorespond to + * the set which can be used with this version of fb. + */ + +Bool +fbInitVisuals (VisualPtr *visualp, + DepthPtr *depthp, + int *nvisualp, + int *ndepthp, + int *rootDepthp, + VisualID *defaultVisp, + unsigned long sizes, + int bitsPerRGB) +{ + return miInitVisuals(visualp, depthp, nvisualp, ndepthp, rootDepthp, + defaultVisp, sizes, bitsPerRGB, -1); +} +#endif diff --git a/fb/fbcompose.c b/fb/fbcompose.c new file mode 100644 index 000000000..b7733dbb5 --- /dev/null +++ b/fb/fbcompose.c @@ -0,0 +1,2897 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fbcompose.c,v 1.16 2002/11/06 22:45:35 keithp Exp $ + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#include "fb.h" +#include "picturestr.h" +#include "mipict.h" +#include "fbpict.h" + +/* + * General purpose compositing code optimized for minimal memory + * references + * + * All work is done on canonical ARGB values, functions for fetching + * and storing these exist for each format. + */ + +/* + * Combine src and mask using IN + */ + +CARD32 +fbCombineMaskU (FbCompositeOperand *src, + FbCompositeOperand *msk) +{ + CARD32 x; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + if (!msk) + return (*src->fetch) (src); + + a = (*msk->fetch) (msk) >> 24; + if (!a) + return 0; + + x = (*src->fetch) (src); + if (a == 0xff) + return x; + + m = FbInU(x,0,a,t); + n = FbInU(x,8,a,t); + o = FbInU(x,16,a,t); + p = FbInU(x,24,a,t); + return m|n|o|p; +} + +FbCompSrc +fbCombineMaskC (FbCompositeOperand *src, + FbCompositeOperand *msk) +{ + FbCompSrc s; + CARD32 x; + CARD32 a; + CARD16 xa; + CARD16 t; + CARD32 m,n,o,p; + + if (!msk) + { + x = (*src->fetch) (src); + s.value = x; + x = x >> 24; + x |= x << 8; + x |= x << 16; + s.alpha = x; + return s; + } + + a = (*msk->fetcha) (msk); + if (!a) + { + s.value = 0; + s.alpha = 0; + return s; + } + + x = (*src->fetch) (src); + if (a == 0xffffffff) + { + s.value = x; + x = x >> 24; + x |= x << 8; + x |= x << 16; + s.alpha = x; + return s; + } + + m = FbInC(x,0,a,t); + n = FbInC(x,8,a,t); + o = FbInC(x,16,a,t); + p = FbInC(x,24,a,t); + s.value = m|n|o|p; + xa = x >> 24; + m = FbInU(a,0,xa,t); + n = FbInU(a,8,xa,t); + o = FbInU(a,16,xa,t); + p = FbInU(a,24,xa,t); + s.alpha = m|n|o|p; + return s; +} + +CARD32 +fbCombineMaskValueC (FbCompositeOperand *src, + FbCompositeOperand *msk) +{ + CARD32 x; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + if (!msk) + { + return (*src->fetch) (src); + } + + a = (*msk->fetcha) (msk); + if (!a) + return a; + + x = (*src->fetch) (src); + if (a == 0xffffffff) + return x; + + m = FbInC(x,0,a,t); + n = FbInC(x,8,a,t); + o = FbInC(x,16,a,t); + p = FbInC(x,24,a,t); + return m|n|o|p; +} + +/* + * Combine src and mask using IN, generating only the alpha component + */ +CARD32 +fbCombineMaskAlphaU (FbCompositeOperand *src, + FbCompositeOperand *msk) +{ + CARD32 x; + CARD16 a; + CARD16 t; + + if (!msk) + return (*src->fetch) (src); + + a = (*msk->fetch) (msk) >> 24; + if (!a) + return 0; + + x = (*src->fetch) (src); + if (a == 0xff) + return x; + + return FbInU(x,24,a,t); +} + +CARD32 +fbCombineMaskAlphaC (FbCompositeOperand *src, + FbCompositeOperand *msk) +{ + CARD32 x; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + if (!msk) + return (*src->fetch) (src); + + a = (*msk->fetcha) (msk); + if (!a) + return 0; + + x = (*src->fetcha) (src); + if (a == 0xffffffff) + return x; + + m = FbInC(x,0,a,t); + n = FbInC(x,8,a,t); + o = FbInC(x,16,a,t); + p = FbInC(x,24,a,t); + return m|n|o|p; +} + +/* + * All of the composing functions + */ +void +fbCombineClear (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + (*dst->store) (dst, 0); +} + +void +fbCombineSrcU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + (*dst->store) (dst, fbCombineMaskU (src, msk)); +} + +void +fbCombineSrcC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + (*dst->store) (dst, fbCombineMaskValueC (src, msk)); +} + +void +fbCombineDst (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + /* noop */ +} + +void +fbCombineOverU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + a = ~s >> 24; + if (a != 0xff) + { + if (a) + { + d = (*dst->fetch) (dst); + m = FbOverU(s,d,0,a,t); + n = FbOverU(s,d,8,a,t); + o = FbOverU(s,d,16,a,t); + p = FbOverU(s,d,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } +} + +void +fbCombineOverC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + FbCompSrc cs; + CARD32 s, d; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + cs = fbCombineMaskC (src, msk); + s = cs.value; + a = ~cs.alpha; + if (a != 0xffffffff) + { + if (a) + { + d = (*dst->fetch) (dst); + m = FbOverC(s,d,0,a,t); + n = FbOverC(s,d,8,a,t); + o = FbOverC(s,d,16,a,t); + p = FbOverC(s,d,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } +} + +void +fbCombineOverReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = ~d >> 24; + if (a) + { + s = fbCombineMaskU (src, msk); + if (a != 0xff) + { + m = FbOverU(d,s,0,a,t); + n = FbOverU(d,s,8,a,t); + o = FbOverU(d,s,16,a,t); + p = FbOverU(d,s,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } +} + +void +fbCombineOverReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = ~d >> 24; + if (a) + { + s = fbCombineMaskValueC (src, msk); + if (a != 0xff) + { + m = FbOverU(d,s,0,a,t); + n = FbOverU(d,s,8,a,t); + o = FbOverU(d,s,16,a,t); + p = FbOverU(d,s,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } +} + +void +fbCombineInU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = d >> 24; + s = 0; + if (a) + { + s = fbCombineMaskU (src, msk); + if (a != 0xff) + { + m = FbInU(s,0,a,t); + n = FbInU(s,8,a,t); + o = FbInU(s,16,a,t); + p = FbInU(s,24,a,t); + s = m|n|o|p; + } + } + (*dst->store) (dst, s); +} + +void +fbCombineInC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = d >> 24; + s = 0; + if (a) + { + s = fbCombineMaskValueC (src, msk); + if (a != 0xff) + { + m = FbInU(s,0,a,t); + n = FbInU(s,8,a,t); + o = FbInU(s,16,a,t); + p = FbInU(s,24,a,t); + s = m|n|o|p; + } + } + (*dst->store) (dst, s); +} + +void +fbCombineInReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskAlphaU (src, msk); + a = s >> 24; + if (a != 0xff) + { + d = 0; + if (a) + { + d = (*dst->fetch) (dst); + m = FbInU(d,0,a,t); + n = FbInU(d,8,a,t); + o = FbInU(d,16,a,t); + p = FbInU(d,24,a,t); + d = m|n|o|p; + } + (*dst->store) (dst, d); + } +} + +void +fbCombineInReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskAlphaC (src, msk); + a = s; + if (a != 0xffffffff) + { + d = 0; + if (a) + { + d = (*dst->fetch) (dst); + m = FbInC(d,0,a,t); + n = FbInC(d,8,a,t); + o = FbInC(d,16,a,t); + p = FbInC(d,24,a,t); + d = m|n|o|p; + } + (*dst->store) (dst, d); + } +} + +void +fbCombineOutU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = ~d >> 24; + s = 0; + if (a) + { + s = fbCombineMaskU (src, msk); + if (a != 0xff) + { + m = FbInU(s,0,a,t); + n = FbInU(s,8,a,t); + o = FbInU(s,16,a,t); + p = FbInU(s,24,a,t); + s = m|n|o|p; + } + } + (*dst->store) (dst, s); +} + +void +fbCombineOutC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + a = ~d >> 24; + s = 0; + if (a) + { + s = fbCombineMaskValueC (src, msk); + if (a != 0xff) + { + m = FbInU(s,0,a,t); + n = FbInU(s,8,a,t); + o = FbInU(s,16,a,t); + p = FbInU(s,24,a,t); + s = m|n|o|p; + } + } + (*dst->store) (dst, s); +} + +void +fbCombineOutReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskAlphaU (src, msk); + a = ~s >> 24; + if (a != 0xff) + { + d = 0; + if (a) + { + d = (*dst->fetch) (dst); + m = FbInU(d,0,a,t); + n = FbInU(d,8,a,t); + o = FbInU(d,16,a,t); + p = FbInU(d,24,a,t); + d = m|n|o|p; + } + (*dst->store) (dst, d); + } +} + +void +fbCombineOutReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD32 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskAlphaC (src, msk); + a = ~s; + if (a != 0xffffffff) + { + d = 0; + if (a) + { + d = (*dst->fetch) (dst); + m = FbInC(d,0,a,t); + n = FbInC(d,8,a,t); + o = FbInC(d,16,a,t); + p = FbInC(d,24,a,t); + d = m|n|o|p; + } + (*dst->store) (dst, d); + } +} + +void +fbCombineAtopU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 ad, as; + CARD16 t,u,v; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + d = (*dst->fetch) (dst); + ad = ~s >> 24; + as = d >> 24; + m = FbGen(s,d,0,as,ad,t,u,v); + n = FbGen(s,d,8,as,ad,t,u,v); + o = FbGen(s,d,16,as,ad,t,u,v); + p = FbGen(s,d,24,as,ad,t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineAtopC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + FbCompSrc cs; + CARD32 s, d; + CARD32 ad; + CARD16 as; + CARD16 t, u, v; + CARD32 m,n,o,p; + + cs = fbCombineMaskC (src, msk); + d = (*dst->fetch) (dst); + s = cs.value; + ad = cs.alpha; + as = d >> 24; + m = FbGen(s,d,0,as,FbGet8(ad,0),t,u,v); + n = FbGen(s,d,8,as,FbGet8(ad,8),t,u,v); + o = FbGen(s,d,16,as,FbGet8(ad,16),t,u,v); + p = FbGen(s,d,24,as,FbGet8(ad,24),t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineAtopReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 ad, as; + CARD16 t, u, v; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + d = (*dst->fetch) (dst); + ad = s >> 24; + as = ~d >> 24; + m = FbGen(s,d,0,as,ad,t,u,v); + n = FbGen(s,d,8,as,ad,t,u,v); + o = FbGen(s,d,16,as,ad,t,u,v); + p = FbGen(s,d,24,as,ad,t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineAtopReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + FbCompSrc cs; + CARD32 s, d, ad; + CARD16 as; + CARD16 t, u, v; + CARD32 m,n,o,p; + + cs = fbCombineMaskC (src, msk); + d = (*dst->fetch) (dst); + s = cs.value; + ad = cs.alpha; + as = ~d >> 24; + m = FbGen(s,d,0,as,FbGet8(ad,0),t,u,v); + n = FbGen(s,d,8,as,FbGet8(ad,8),t,u,v); + o = FbGen(s,d,16,as,FbGet8(ad,16),t,u,v); + p = FbGen(s,d,24,as,FbGet8(ad,24),t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineXorU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 ad, as; + CARD16 t, u, v; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + d = (*dst->fetch) (dst); + ad = ~s >> 24; + as = ~d >> 24; + m = FbGen(s,d,0,as,ad,t,u,v); + n = FbGen(s,d,8,as,ad,t,u,v); + o = FbGen(s,d,16,as,ad,t,u,v); + p = FbGen(s,d,24,as,ad,t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineXorC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + FbCompSrc cs; + CARD32 s, d, ad; + CARD16 as; + CARD16 t, u, v; + CARD32 m,n,o,p; + + cs = fbCombineMaskC (src, msk); + d = (*dst->fetch) (dst); + s = cs.value; + ad = ~cs.alpha; + as = ~d >> 24; + m = FbGen(s,d,0,as,ad,t,u,v); + n = FbGen(s,d,8,as,ad,t,u,v); + o = FbGen(s,d,16,as,ad,t,u,v); + p = FbGen(s,d,24,as,ad,t,u,v); + (*dst->store) (dst, m|n|o|p); +} + +void +fbCombineAddU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + if (s == ~0) + (*dst->store) (dst, s); + else + { + d = (*dst->fetch) (dst); + if (s && d != ~0) + { + m = FbAdd(s,d,0,t); + n = FbAdd(s,d,8,t); + o = FbAdd(s,d,16,t); + p = FbAdd(s,d,24,t); + (*dst->store) (dst, m|n|o|p); + } + } +} + +void +fbCombineAddC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskValueC (src, msk); + if (s == ~0) + (*dst->store) (dst, s); + else + { + d = (*dst->fetch) (dst); + if (s && d != ~0) + { + m = FbAdd(s,d,0,t); + n = FbAdd(s,d,8,t); + o = FbAdd(s,d,16,t); + p = FbAdd(s,d,24,t); + (*dst->store) (dst, m|n|o|p); + } + } +} + +void +fbCombineSaturateU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s = fbCombineMaskU (src, msk), d; +#if 0 + CARD16 sa, da; + CARD16 ad, as; + CARD16 t; + CARD32 m,n,o,p; + + d = (*dst->fetch) (dst); + sa = s >> 24; + da = ~d >> 24; + if (sa <= da) + { + m = FbAdd(s,d,0,t); + n = FbAdd(s,d,8,t); + o = FbAdd(s,d,16,t); + p = FbAdd(s,d,24,t); + } + else + { + as = (da << 8) / sa; + ad = 0xff; + m = FbGen(s,d,0,as,ad,t,u,v); + n = FbGen(s,d,8,as,ad,t,u,v); + o = FbGen(s,d,16,as,ad,t,u,v); + p = FbGen(s,d,24,as,ad,t,u,v); + } + (*dst->store) (dst, m|n|o|p); +#else + if ((s >> 24) == 0xff) + (*dst->store) (dst, s); + else + { + d = (*dst->fetch) (dst); + if ((s >> 24) > (d >> 24)) + (*dst->store) (dst, s); + } +#endif +} + +void +fbCombineSaturateC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + FbCompSrc cs; + CARD32 s, d; + CARD16 sa, sr, sg, sb, da; + CARD16 t, u, v; + CARD32 m,n,o,p; + + cs = fbCombineMaskC (src, msk); + d = (*dst->fetch) (dst); + s = cs.value; + sa = (cs.alpha >> 24) & 0xff; + sr = (cs.alpha >> 16) & 0xff; + sg = (cs.alpha >> 8) & 0xff; + sb = (cs.alpha ) & 0xff; + da = ~d >> 24; + + if (sb <= da) + m = FbAdd(s,d,0,t); + else + m = FbGen (s, d, 0, (da << 8) / sb, 0xff, t, u, v); + + if (sg <= da) + n = FbAdd(s,d,8,t); + else + n = FbGen (s, d, 8, (da << 8) / sg, 0xff, t, u, v); + + if (sr < da) + o = FbAdd(s,d,16,t); + else + o = FbGen (s, d, 16, (da << 8) / sr, 0xff, t, u, v); + + if (sa <= da) + p = FbAdd(s,d,24,t); + else + p = FbGen (s, d, 24, (da << 8) / sa, 0xff, t, u, v); + + (*dst->store) (dst, m|n|o|p); +} + +/* + * All of the disjoint composing functions + + The four entries in the first column indicate what source contributions + come from each of the four areas of the picture -- areas covered by neither + A nor B, areas covered only by A, areas covered only by B and finally + areas covered by both A and B. + + Disjoint Conjoint + Fa Fb Fa Fb +(0,0,0,0) 0 0 0 0 +(0,A,0,A) 1 0 1 0 +(0,0,B,B) 0 1 0 1 +(0,A,B,A) 1 min((1-a)/b,1) 1 max(1-a/b,0) +(0,A,B,B) min((1-b)/a,1) 1 max(1-b/a,0) 1 +(0,0,0,A) max(1-(1-b)/a,0) 0 min(1,b/a) 0 +(0,0,0,B) 0 max(1-(1-a)/b,0) 0 min(a/b,1) +(0,A,0,0) min(1,(1-b)/a) 0 max(1-b/a,0) 0 +(0,0,B,0) 0 min(1,(1-a)/b) 0 max(1-a/b,0) +(0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0) +(0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b) +(0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0) + + */ + +#define CombineAOut 1 +#define CombineAIn 2 +#define CombineBOut 4 +#define CombineBIn 8 + +#define CombineClear 0 +#define CombineA (CombineAOut|CombineAIn) +#define CombineB (CombineBOut|CombineBIn) +#define CombineAOver (CombineAOut|CombineBOut|CombineAIn) +#define CombineBOver (CombineAOut|CombineBOut|CombineBIn) +#define CombineAAtop (CombineBOut|CombineAIn) +#define CombineBAtop (CombineAOut|CombineBIn) +#define CombineXor (CombineAOut|CombineBOut) + +/* portion covered by a but not b */ +CARD8 +fbCombineDisjointOutPart (CARD8 a, CARD8 b) +{ + /* min (1, (1-b) / a) */ + + b = ~b; /* 1 - b */ + if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ + return 0xff; /* 1 */ + return FbIntDiv(b,a); /* (1-b) / a */ +} + +/* portion covered by both a and b */ +CARD8 +fbCombineDisjointInPart (CARD8 a, CARD8 b) +{ + /* max (1-(1-b)/a,0) */ + /* = - min ((1-b)/a - 1, 0) */ + /* = 1 - min (1, (1-b)/a) */ + + b = ~b; /* 1 - b */ + if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ + return 0; /* 1 - 1 */ + return ~FbIntDiv(b,a); /* 1 - (1-b) / a */ +} + +void +fbCombineDisjointGeneralU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine) +{ + CARD32 s, d; + CARD32 m,n,o,p; + CARD16 Fa, Fb, t, u, v; + CARD8 sa, da; + + s = fbCombineMaskU (src, msk); + sa = s >> 24; + + d = (*dst->fetch) (dst); + da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + Fa = fbCombineDisjointOutPart (sa, da); + break; + case CombineAIn: + Fa = fbCombineDisjointInPart (sa, da); + break; + case CombineA: + Fa = 0xff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + Fb = fbCombineDisjointOutPart (da, sa); + break; + case CombineBIn: + Fb = fbCombineDisjointInPart (da, sa); + break; + case CombineB: + Fb = 0xff; + break; + } + m = FbGen (s,d,0,Fa,Fb,t,u,v); + n = FbGen (s,d,8,Fa,Fb,t,u,v); + o = FbGen (s,d,16,Fa,Fb,t,u,v); + p = FbGen (s,d,24,Fa,Fb,t,u,v); + s = m|n|o|p; + (*dst->store) (dst, s); +} + +void +fbCombineDisjointGeneralC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine) +{ + FbCompSrc cs; + CARD32 s, d; + CARD32 m,n,o,p; + CARD32 Fa; + CARD16 Fb, t, u, v; + CARD32 sa; + CARD8 da; + + cs = fbCombineMaskC (src, msk); + s = cs.value; + sa = cs.alpha; + + d = (*dst->fetch) (dst); + da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + m = fbCombineDisjointOutPart ((CARD8) (sa >> 0), da); + n = fbCombineDisjointOutPart ((CARD8) (sa >> 8), da) << 8; + o = fbCombineDisjointOutPart ((CARD8) (sa >> 16), da) << 16; + p = fbCombineDisjointOutPart ((CARD8) (sa >> 24), da) << 24; + Fa = m|n|o|p; + break; + case CombineAIn: + m = fbCombineDisjointOutPart ((CARD8) (sa >> 0), da); + n = fbCombineDisjointOutPart ((CARD8) (sa >> 8), da) << 8; + o = fbCombineDisjointOutPart ((CARD8) (sa >> 16), da) << 16; + p = fbCombineDisjointOutPart ((CARD8) (sa >> 24), da) << 24; + Fa = m|n|o|p; + break; + case CombineA: + Fa = 0xffffffff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + Fb = fbCombineDisjointOutPart (da, sa); + break; + case CombineBIn: + Fb = fbCombineDisjointInPart (da, sa); + break; + case CombineB: + Fb = 0xff; + break; + } + m = FbGen (s,d,0,FbGet8(Fa,0),Fb,t,u,v); + n = FbGen (s,d,8,FbGet8(Fa,8),Fb,t,u,v); + o = FbGen (s,d,16,FbGet8(Fa,16),Fb,t,u,v); + p = FbGen (s,d,24,FbGet8(Fa,24),Fb,t,u,v); + s = m|n|o|p; + (*dst->store) (dst, s); +} + +void +fbCombineDisjointOverU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + a = s >> 24; + if (a != 0x00) + { + if (a != 0xff) + { + d = (*dst->fetch) (dst); + a = fbCombineDisjointOutPart (d >> 24, a); + m = FbOverU(s,d,0,a,t); + n = FbOverU(s,d,8,a,t); + o = FbOverU(s,d,16,a,t); + p = FbOverU(s,d,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } +} + +void +fbCombineDisjointOverC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineAOver); +} + +void +fbCombineDisjointOverReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineBOver); +} + +void +fbCombineDisjointOverReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineBOver); +} + +void +fbCombineDisjointInU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineAIn); +} + +void +fbCombineDisjointInC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineAIn); +} + +void +fbCombineDisjointInReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineBIn); +} + +void +fbCombineDisjointInReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineBIn); +} + +void +fbCombineDisjointOutU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineAOut); +} + +void +fbCombineDisjointOutC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineAOut); +} + +void +fbCombineDisjointOutReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineBOut); +} + +void +fbCombineDisjointOutReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineBOut); +} + +void +fbCombineDisjointAtopU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineAAtop); +} + +void +fbCombineDisjointAtopC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineAAtop); +} + +void +fbCombineDisjointAtopReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineBAtop); +} + +void +fbCombineDisjointAtopReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineBAtop); +} + +void +fbCombineDisjointXorU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralU (src, msk, dst, CombineXor); +} + +void +fbCombineDisjointXorC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineDisjointGeneralC (src, msk, dst, CombineXor); +} + +/* portion covered by a but not b */ +CARD8 +fbCombineConjointOutPart (CARD8 a, CARD8 b) +{ + /* max (1-b/a,0) */ + /* = 1-min(b/a,1) */ + + /* min (1, (1-b) / a) */ + + if (b >= a) /* b >= a -> b/a >= 1 */ + return 0x00; /* 0 */ + return ~FbIntDiv(b,a); /* 1 - b/a */ +} + +/* portion covered by both a and b */ +CARD8 +fbCombineConjointInPart (CARD8 a, CARD8 b) +{ + /* min (1,b/a) */ + + if (b >= a) /* b >= a -> b/a >= 1 */ + return 0xff; /* 1 */ + return FbIntDiv(b,a); /* b/a */ +} + +void +fbCombineConjointGeneralU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine) +{ + CARD32 s, d; + CARD32 m,n,o,p; + CARD16 Fa, Fb, t, u, v; + CARD8 sa, da; + + s = fbCombineMaskU (src, msk); + sa = s >> 24; + + d = (*dst->fetch) (dst); + da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + Fa = fbCombineConjointOutPart (sa, da); + break; + case CombineAIn: + Fa = fbCombineConjointInPart (sa, da); + break; + case CombineA: + Fa = 0xff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + Fb = fbCombineConjointOutPart (da, sa); + break; + case CombineBIn: + Fb = fbCombineConjointInPart (da, sa); + break; + case CombineB: + Fb = 0xff; + break; + } + m = FbGen (s,d,0,Fa,Fb,t,u,v); + n = FbGen (s,d,8,Fa,Fb,t,u,v); + o = FbGen (s,d,16,Fa,Fb,t,u,v); + p = FbGen (s,d,24,Fa,Fb,t,u,v); + s = m|n|o|p; + (*dst->store) (dst, s); +} + +void +fbCombineConjointGeneralC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine) +{ + FbCompSrc cs; + CARD32 s, d; + CARD32 m,n,o,p; + CARD32 Fa; + CARD16 Fb, t, u, v; + CARD32 sa; + CARD8 da; + + cs = fbCombineMaskC (src, msk); + s = cs.value; + sa = cs.alpha; + + d = (*dst->fetch) (dst); + da = d >> 24; + + switch (combine & CombineA) { + default: + Fa = 0; + break; + case CombineAOut: + m = fbCombineConjointOutPart ((CARD8) (sa >> 0), da); + n = fbCombineConjointOutPart ((CARD8) (sa >> 8), da) << 8; + o = fbCombineConjointOutPart ((CARD8) (sa >> 16), da) << 16; + p = fbCombineConjointOutPart ((CARD8) (sa >> 24), da) << 24; + Fa = m|n|o|p; + break; + case CombineAIn: + m = fbCombineConjointOutPart ((CARD8) (sa >> 0), da); + n = fbCombineConjointOutPart ((CARD8) (sa >> 8), da) << 8; + o = fbCombineConjointOutPart ((CARD8) (sa >> 16), da) << 16; + p = fbCombineConjointOutPart ((CARD8) (sa >> 24), da) << 24; + Fa = m|n|o|p; + break; + case CombineA: + Fa = 0xffffffff; + break; + } + + switch (combine & CombineB) { + default: + Fb = 0; + break; + case CombineBOut: + Fb = fbCombineConjointOutPart (da, sa); + break; + case CombineBIn: + Fb = fbCombineConjointInPart (da, sa); + break; + case CombineB: + Fb = 0xff; + break; + } + m = FbGen (s,d,0,FbGet8(Fa,0),Fb,t,u,v); + n = FbGen (s,d,8,FbGet8(Fa,8),Fb,t,u,v); + o = FbGen (s,d,16,FbGet8(Fa,16),Fb,t,u,v); + p = FbGen (s,d,24,FbGet8(Fa,24),Fb,t,u,v); + s = m|n|o|p; + (*dst->store) (dst, s); +} + +void +fbCombineConjointOverU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineAOver); +/* + CARD32 s, d; + CARD16 a; + CARD16 t; + CARD32 m,n,o,p; + + s = fbCombineMaskU (src, msk); + a = s >> 24; + if (a != 0x00) + { + if (a != 0xff) + { + d = (*dst->fetch) (dst); + a = fbCombineConjointOutPart (d >> 24, a); + m = FbOverU(s,d,0,a,t); + n = FbOverU(s,d,8,a,t); + o = FbOverU(s,d,16,a,t); + p = FbOverU(s,d,24,a,t); + s = m|n|o|p; + } + (*dst->store) (dst, s); + } + */ +} + +void +fbCombineConjointOverC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineAOver); +} + +void +fbCombineConjointOverReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineBOver); +} + +void +fbCombineConjointOverReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineBOver); +} + +void +fbCombineConjointInU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineAIn); +} + +void +fbCombineConjointInC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineAIn); +} + +void +fbCombineConjointInReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineBIn); +} + +void +fbCombineConjointInReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineBIn); +} + +void +fbCombineConjointOutU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineAOut); +} + +void +fbCombineConjointOutC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineAOut); +} + +void +fbCombineConjointOutReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineBOut); +} + +void +fbCombineConjointOutReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineBOut); +} + +void +fbCombineConjointAtopU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineAAtop); +} + +void +fbCombineConjointAtopC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineAAtop); +} + +void +fbCombineConjointAtopReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineBAtop); +} + +void +fbCombineConjointAtopReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineBAtop); +} + +void +fbCombineConjointXorU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralU (src, msk, dst, CombineXor); +} + +void +fbCombineConjointXorC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst) +{ + fbCombineConjointGeneralC (src, msk, dst, CombineXor); +} + +FbCombineFunc fbCombineFuncU[] = { + fbCombineClear, + fbCombineSrcU, + fbCombineDst, + fbCombineOverU, + fbCombineOverReverseU, + fbCombineInU, + fbCombineInReverseU, + fbCombineOutU, + fbCombineOutReverseU, + fbCombineAtopU, + fbCombineAtopReverseU, + fbCombineXorU, + fbCombineAddU, + fbCombineDisjointOverU, /* Saturate */ + 0, + 0, + fbCombineClear, + fbCombineSrcU, + fbCombineDst, + fbCombineDisjointOverU, + fbCombineDisjointOverReverseU, + fbCombineDisjointInU, + fbCombineDisjointInReverseU, + fbCombineDisjointOutU, + fbCombineDisjointOutReverseU, + fbCombineDisjointAtopU, + fbCombineDisjointAtopReverseU, + fbCombineDisjointXorU, + 0, + 0, + 0, + 0, + fbCombineClear, + fbCombineSrcU, + fbCombineDst, + fbCombineConjointOverU, + fbCombineConjointOverReverseU, + fbCombineConjointInU, + fbCombineConjointInReverseU, + fbCombineConjointOutU, + fbCombineConjointOutReverseU, + fbCombineConjointAtopU, + fbCombineConjointAtopReverseU, + fbCombineConjointXorU, +}; + +FbCombineFunc fbCombineFuncC[] = { + fbCombineClear, + fbCombineSrcC, + fbCombineDst, + fbCombineOverC, + fbCombineOverReverseC, + fbCombineInC, + fbCombineInReverseC, + fbCombineOutC, + fbCombineOutReverseC, + fbCombineAtopC, + fbCombineAtopReverseC, + fbCombineXorC, + fbCombineAddC, + fbCombineDisjointOverC, /* Saturate */ + 0, + 0, + fbCombineClear, /* 0x10 */ + fbCombineSrcC, + fbCombineDst, + fbCombineDisjointOverC, + fbCombineDisjointOverReverseC, + fbCombineDisjointInC, + fbCombineDisjointInReverseC, + fbCombineDisjointOutC, + fbCombineDisjointOutReverseC, + fbCombineDisjointAtopC, + fbCombineDisjointAtopReverseC, + fbCombineDisjointXorC, /* 0x1b */ + 0, + 0, + 0, + 0, + fbCombineClear, + fbCombineSrcC, + fbCombineDst, + fbCombineConjointOverC, + fbCombineConjointOverReverseC, + fbCombineConjointInC, + fbCombineConjointInReverseC, + fbCombineConjointOutC, + fbCombineConjointOutReverseC, + fbCombineConjointAtopC, + fbCombineConjointAtopReverseC, + fbCombineConjointXorC, +}; + +/* + * All of the fetch functions + */ + +CARD32 +fbFetch_a8r8g8b8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + return ((CARD32 *)line)[offset >> 5]; +} + +CARD32 +fbFetch_x8r8g8b8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + return ((CARD32 *)line)[offset >> 5] | 0xff000000; +} + +CARD32 +fbFetch_a8b8g8r8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + + return ((pixel & 0xff000000) | + ((pixel >> 16) & 0xff) | + (pixel & 0x0000ff00) | + ((pixel & 0xff) << 16)); +} + +CARD32 +fbFetch_x8b8g8r8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + + return ((0xff000000) | + ((pixel >> 16) & 0xff) | + (pixel & 0x0000ff00) | + ((pixel & 0xff) << 16)); +} + +CARD32 +fbFetch_r8g8b8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); +#if IMAGE_BYTE_ORDER == MSBFirst + return (0xff000000 | + (pixel[0] << 16) | + (pixel[1] << 8) | + (pixel[2])); +#else + return (0xff000000 | + (pixel[2] << 16) | + (pixel[1] << 8) | + (pixel[0])); +#endif +} + +CARD32 +fbFetch_b8g8r8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); +#if IMAGE_BYTE_ORDER == MSBFirst + return (0xff000000 | + (pixel[2] << 16) | + (pixel[1] << 8) | + (pixel[0])); +#else + return (0xff000000 | + (pixel[0] << 16) | + (pixel[1] << 8) | + (pixel[2])); +#endif +} + +CARD32 +fbFetch_r5g6b5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + r = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) << 8; + g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_b5g6r5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + b = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) >> 8; + g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a1r5g5b5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 a,r,g,b; + + a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24; + r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + return (a | r | g | b); +} + +CARD32 +fbFetch_x1r5g5b5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2; + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a1b5g5r5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 a,r,g,b; + + a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24; + b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + return (a | r | g | b); +} + +CARD32 +fbFetch_x1b5g5r5 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7; + g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6; + r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14; + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a4r4g4b4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 a,r,g,b; + + a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16; + r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + return (a | r | g | b); +} + +CARD32 +fbFetch_x4r4g4b4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a4b4g4r4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 a,r,g,b; + + a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16; + b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + return (a | r | g | b); +} + +CARD32 +fbFetch_x4b4g4r4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD16 *) line)[offset >> 4]; + CARD32 r,g,b; + + b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12; + g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8; + r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)); + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + + return pixel << 24; +} + +CARD32 +fbFetcha_a8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + + pixel |= pixel << 8; + pixel |= pixel << 16; + return pixel; +} + +CARD32 +fbFetch_r3g3b2 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + CARD32 r,g,b; + + r = ((pixel & 0xe0) | ((pixel & 0xe0) >> 3) | ((pixel & 0xc0) >> 6)) << 16; + g = ((pixel & 0x1c) | ((pixel & 0x18) >> 3) | ((pixel & 0x1c) << 3)) << 8; + b = (((pixel & 0x03) ) | + ((pixel & 0x03) << 2) | + ((pixel & 0x03) << 4) | + ((pixel & 0x03) << 6)); + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_b2g3r3 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + CARD32 r,g,b; + + b = (((pixel & 0xc0) ) | + ((pixel & 0xc0) >> 2) | + ((pixel & 0xc0) >> 4) | + ((pixel & 0xc0) >> 6)); + g = ((pixel & 0x38) | ((pixel & 0x38) >> 3) | ((pixel & 0x30) << 2)) << 8; + r = (((pixel & 0x07) ) | + ((pixel & 0x07) << 3) | + ((pixel & 0x06) << 6)) << 16; + return (0xff000000 | r | g | b); +} + +CARD32 +fbFetch_a2r2g2b2 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + CARD32 a,r,g,b; + + a = ((pixel & 0xc0) * 0x55) << 18; + r = ((pixel & 0x30) * 0x55) << 12; + g = ((pixel & 0x0c) * 0x55) << 6; + b = ((pixel & 0x03) * 0x55); + return a|r|g|b; +} + +CARD32 +fbFetch_a2b2g2r2 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + CARD32 a,r,g,b; + + a = ((pixel & 0xc0) * 0x55) << 18; + b = ((pixel & 0x30) * 0x55) >> 6; + g = ((pixel & 0x0c) * 0x55) << 6; + r = ((pixel & 0x03) * 0x55) << 16; + return a|r|g|b; +} + +CARD32 +fbFetch_c8 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD8 *) line)[offset>>3]; + + return op->indexed->rgba[pixel]; +} + +#define Fetch8(l,o) (((CARD8 *) (l))[(o) >> 3]) +#if IMAGE_BYTE_ORDER == MSBFirst +#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) & 0xf : Fetch8(l,o) >> 4) +#else +#define Fetch4(l,o) ((o) & 2 ? Fetch8(l,o) >> 4 : Fetch8(l,o) & 0xf) +#endif + +CARD32 +fbFetch_a4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + + pixel |= pixel << 4; + return pixel << 24; +} + +CARD32 +fbFetcha_a4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + + pixel |= pixel << 4; + pixel |= pixel << 8; + pixel |= pixel << 16; + return pixel; +} + +CARD32 +fbFetch_r1g2b1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + CARD32 r,g,b; + + r = ((pixel & 0x8) * 0xff) << 13; + g = ((pixel & 0x6) * 0x55) << 7; + b = ((pixel & 0x1) * 0xff); + return 0xff000000|r|g|b; +} + +CARD32 +fbFetch_b1g2r1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + CARD32 r,g,b; + + b = ((pixel & 0x8) * 0xff) >> 3; + g = ((pixel & 0x6) * 0x55) << 7; + r = ((pixel & 0x1) * 0xff) << 16; + return 0xff000000|r|g|b; +} + +CARD32 +fbFetch_a1r1g1b1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + CARD32 a,r,g,b; + + a = ((pixel & 0x8) * 0xff) << 21; + r = ((pixel & 0x4) * 0xff) << 14; + g = ((pixel & 0x2) * 0xff) << 7; + b = ((pixel & 0x1) * 0xff); + return a|r|g|b; +} + +CARD32 +fbFetch_a1b1g1r1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + CARD32 a,r,g,b; + + a = ((pixel & 0x8) * 0xff) << 21; + r = ((pixel & 0x4) * 0xff) >> 3; + g = ((pixel & 0x2) * 0xff) << 7; + b = ((pixel & 0x1) * 0xff) << 16; + return a|r|g|b; +} + +CARD32 +fbFetch_c4 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = Fetch4(line, offset); + + return op->indexed->rgba[pixel]; +} + +CARD32 +fbFetcha_a1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + CARD32 a; +#if BITMAP_BIT_ORDER == MSBFirst + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + a |= a << 1; + a |= a << 2; + a |= a << 4; + a |= a << 8; + a |= a << 16; + return a; +} + +CARD32 +fbFetch_a1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + CARD32 a; +#if BITMAP_BIT_ORDER == MSBFirst + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + a |= a << 1; + a |= a << 2; + a |= a << 4; + return a << 24; +} + +CARD32 +fbFetch_g1 (FbCompositeOperand *op) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel = ((CARD32 *)line)[offset >> 5]; + CARD32 a; +#if BITMAP_BIT_ORDER == MSBFirst + a = pixel >> (0x1f - (offset & 0x1f)); +#else + a = pixel >> (offset & 0x1f); +#endif + a = a & 1; + return op->indexed->rgba[a]; +} + +/* + * All the store functions + */ + +#define Splita(v) CARD32 a = ((v) >> 24), r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff +#define Split(v) CARD32 r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff + +void +fbStore_a8r8g8b8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + ((CARD32 *)line)[offset >> 5] = value; +} + +void +fbStore_x8r8g8b8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + ((CARD32 *)line)[offset >> 5] = value & 0xffffff; +} + +void +fbStore_a8b8g8r8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + Splita(value); + ((CARD32 *)line)[offset >> 5] = a << 24 | b << 16 | g << 8 | r; +} + +void +fbStore_x8b8g8r8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + Split(value); + ((CARD32 *)line)[offset >> 5] = b << 16 | g << 8 | r; +} + +void +fbStore_r8g8b8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + Split(value); +#if IMAGE_BYTE_ORDER == MSBFirst + pixel[0] = r; + pixel[1] = g; + pixel[2] = b; +#else + pixel[0] = b; + pixel[1] = g; + pixel[2] = r; +#endif +} + +void +fbStore_b8g8r8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + Split(value); +#if IMAGE_BYTE_ORDER == MSBFirst + pixel[0] = b; + pixel[1] = g; + pixel[2] = r; +#else + pixel[0] = r; + pixel[1] = g; + pixel[2] = b; +#endif +} + +void +fbStore_r5g6b5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((r << 8) & 0xf800) | + ((g << 3) & 0x07e0) | + ((b >> 3) )); +} + +void +fbStore_b5g6r5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((b << 8) & 0xf800) | + ((g << 3) & 0x07e0) | + ((r >> 3) )); +} + +void +fbStore_a1r5g5b5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Splita(value); + *pixel = (((a << 8) & 0x8000) | + ((r << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((b >> 3) )); +} + +void +fbStore_x1r5g5b5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((r << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((b >> 3) )); +} + +void +fbStore_a1b5g5r5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Splita(value); + *pixel = (((a << 8) & 0x8000) | + ((b << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((r >> 3) )); +} + +void +fbStore_x1b5g5r5 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((b << 7) & 0x7c00) | + ((g << 2) & 0x03e0) | + ((r >> 3) )); +} + +void +fbStore_a4r4g4b4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Splita(value); + *pixel = (((a << 8) & 0xf000) | + ((r << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((b >> 4) )); +} + +void +fbStore_x4r4g4b4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((r << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((b >> 4) )); +} + +void +fbStore_a4b4g4r4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Splita(value); + *pixel = (((a << 8) & 0xf000) | + ((b << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((r >> 4) )); +} + +void +fbStore_x4b4g4r4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD16 *pixel = ((CARD16 *) line) + (offset >> 4); + Split(value); + *pixel = (((b << 4) & 0x0f00) | + ((g ) & 0x00f0) | + ((r >> 4) )); +} + +void +fbStore_a8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + *pixel = value >> 24; +} + +void +fbStore_r3g3b2 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + Split(value); + *pixel = (((r ) & 0xe0) | + ((g >> 3) & 0x1c) | + ((b >> 6) )); +} + +void +fbStore_b2g3r3 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + Split(value); + *pixel = (((b ) & 0xe0) | + ((g >> 3) & 0x1c) | + ((r >> 6) )); +} + +void +fbStore_a2r2g2b2 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + Splita(value); + *pixel = (((a ) & 0xc0) | + ((r >> 2) & 0x30) | + ((g >> 4) & 0x0c) | + ((b >> 6) )); +} + +void +fbStore_c8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + *pixel = miIndexToEnt24(op->indexed,value); +} + +void +fbStore_g8 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD8 *pixel = ((CARD8 *) line) + (offset >> 3); + *pixel = miIndexToEntY24(op->indexed,value); +} + +#define Store8(l,o,v) (((CARD8 *) l)[(o) >> 3] = (v)) +#if IMAGE_BYTE_ORDER == MSBFirst +#define Store4(l,o,v) Store8(l,o,((o) & 4 ? \ + (Fetch8(l,o) & 0xf0) | (v) : \ + (Fetch8(l,o) & 0x0f) | ((v) << 4))) +#else +#define Store4(l,o,v) Store8(l,o,((o) & 4 ? \ + (Fetch8(l,o) & 0x0f) | ((v) << 4) : \ + (Fetch8(l,o) & 0xf0) | (v))) +#endif + +void +fbStore_a4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + Store4(line,offset,value>>28); +} + +void +fbStore_r1g2b1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + + Split(value); + pixel = (((r >> 4) & 0x8) | + ((g >> 5) & 0x6) | + ((b >> 7) )); + Store4(line,offset,pixel); +} + +void +fbStore_b1g2r1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + + Split(value); + pixel = (((b >> 4) & 0x8) | + ((g >> 5) & 0x6) | + ((r >> 7) )); + Store4(line,offset,pixel); +} + +void +fbStore_a1r1g1b1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + Splita(value); + pixel = (((a >> 4) & 0x8) | + ((r >> 5) & 0x4) | + ((g >> 6) & 0x2) | + ((b >> 7) )); + Store4(line,offset,pixel); +} + +void +fbStore_a1b1g1r1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + Splita(value); + pixel = (((a >> 4) & 0x8) | + ((b >> 5) & 0x4) | + ((g >> 6) & 0x2) | + ((r >> 7) )); + Store4(line,offset,pixel); +} + +void +fbStore_c4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + + pixel = miIndexToEnt24(op->indexed,value); + Store4(line,offset,pixel); +} + +void +fbStore_g4 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 pixel; + + pixel = miIndexToEntY24(op->indexed,value); + Store4(line,offset,pixel); +} + +void +fbStore_a1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 *pixel = ((CARD32 *) line) + (offset >> 5); + CARD32 mask = FbStipMask(offset & 0x1f, 1); + + value = value & 0x80000000 ? mask : 0; + *pixel = (*pixel & ~mask) | value; +} + +void +fbStore_g1 (FbCompositeOperand *op, CARD32 value) +{ + FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset; + CARD32 *pixel = ((CARD32 *) line) + (offset >> 5); + CARD32 mask = FbStipMask(offset & 0x1f, 1); + + value = miIndexToEntY24(op->indexed,value) ? mask : 0; + *pixel = (*pixel & ~mask) | value; +} + +CARD32 +fbFetch_external (FbCompositeOperand *op) +{ + CARD32 rgb = (*op[1].fetch) (&op[1]); + CARD32 a = (*op[2].fetch) (&op[2]); + + return (rgb & 0xffffff) | (a & 0xff000000); +} + + +CARD32 +fbFetcha_external (FbCompositeOperand *op) +{ + return (*op[2].fetch) (&op[2]); +} + +void +fbStore_external (FbCompositeOperand *op, CARD32 value) +{ + (*op[1].store) (&op[1], value | 0xff000000); + (*op[2].store) (&op[2], value & 0xff000000); +} + +CARD32 +fbFetch_transform (FbCompositeOperand *op) +{ + PictVector v; + int x, y; + int minx, maxx, miny, maxy; + int n; + BoxRec box; + CARD32 rtot, gtot, btot, atot; + CARD32 xerr, yerr; + CARD32 bits; + + v.vector[0] = IntToxFixed(op->u.transform.x); + v.vector[1] = IntToxFixed(op->u.transform.y); + v.vector[2] = xFixed1; + if (!PictureTransformPoint (op->u.transform.transform, &v)) + return 0; + switch (op->u.transform.filter) { + case PictFilterNearest: + y = xFixedToInt (v.vector[1]) + op->u.transform.top_y; + x = xFixedToInt (v.vector[0]) + op->u.transform.left_x; + if (POINT_IN_REGION (0, op->clip, x, y, &box)) + { + (*op[1].set) (&op[1], x, y); + bits = (*op[1].fetch) (&op[1]); + } + else + bits = 0; + break; + case PictFilterBilinear: + rtot = gtot = btot = atot = 0; + miny = xFixedToInt (v.vector[1]) + op->u.transform.top_y; + maxy = xFixedToInt (xFixedCeil (v.vector[1])) + op->u.transform.top_y; + + minx = xFixedToInt (v.vector[0]) + op->u.transform.left_x; + maxx = xFixedToInt (xFixedCeil (v.vector[0])) + op->u.transform.left_x; + + yerr = xFixed1 - xFixedFrac (v.vector[1]); + for (y = miny; y <= maxy; y++) + { + CARD32 lrtot = 0, lgtot = 0, lbtot = 0, latot = 0; + + xerr = xFixed1 - xFixedFrac (v.vector[0]); + for (x = minx; x <= maxx; x++) + { + if (POINT_IN_REGION (0, op->clip, x, y, &box)) + { + (*op[1].set) (&op[1], x, y); + bits = (*op[1].fetch) (&op[1]); + { + Splita(bits); + lrtot += r * xerr; + lgtot += g * xerr; + lbtot += b * xerr; + latot += a * xerr; + n++; + } + } + xerr = xFixed1 - xerr; + } + rtot += (lrtot >> 10) * yerr; + gtot += (lgtot >> 10) * yerr; + btot += (lbtot >> 10) * yerr; + atot += (latot >> 10) * yerr; + yerr = xFixed1 - yerr; + } + if ((atot >>= 22) > 0xff) atot = 0xff; + if ((rtot >>= 22) > 0xff) rtot = 0xff; + if ((gtot >>= 22) > 0xff) gtot = 0xff; + if ((btot >>= 22) > 0xff) btot = 0xff; + bits = ((atot << 24) | + (rtot << 16) | + (gtot << 8) | + (btot )); + break; + default: + bits = 0; + break; + } + return bits; +} + +CARD32 +fbFetcha_transform (FbCompositeOperand *op) +{ + PictVector v; + int x, y; + int minx, maxx, miny, maxy; + int n; + BoxRec box; + CARD32 rtot, gtot, btot, atot; + CARD32 xerr, yerr; + CARD32 bits; + + v.vector[0] = IntToxFixed(op->u.transform.x); + v.vector[1] = IntToxFixed(op->u.transform.y); + v.vector[2] = xFixed1; + if (!PictureTransformPoint (op->u.transform.transform, &v)) + return 0; + switch (op->u.transform.filter) { + case PictFilterNearest: + y = xFixedToInt (v.vector[1]) + op->u.transform.left_x; + x = xFixedToInt (v.vector[0]) + op->u.transform.top_y; + if (POINT_IN_REGION (0, op->clip, x, y, &box)) + { + (*op[1].set) (&op[1], x, y); + bits = (*op[1].fetcha) (&op[1]); + } + else + bits = 0; + break; + case PictFilterBilinear: + rtot = gtot = btot = atot = 0; + + miny = xFixedToInt (v.vector[1]) + op->u.transform.top_y; + maxy = xFixedToInt (xFixedCeil (v.vector[1])) + op->u.transform.top_y; + + minx = xFixedToInt (v.vector[0]) + op->u.transform.left_x; + maxx = xFixedToInt (xFixedCeil (v.vector[0])) + op->u.transform.left_x; + + yerr = xFixed1 - xFixedFrac (v.vector[1]); + for (y = miny; y <= maxy; y++) + { + CARD32 lrtot = 0, lgtot = 0, lbtot = 0, latot = 0; + xerr = xFixed1 - xFixedFrac (v.vector[0]); + for (x = minx; x <= maxx; x++) + { + if (POINT_IN_REGION (0, op->clip, x, y, &box)) + { + (*op[1].set) (&op[1], x, y); + bits = (*op[1].fetcha) (&op[1]); + { + Splita(bits); + lrtot += r * xerr; + lgtot += g * xerr; + lbtot += b * xerr; + latot += a * xerr; + n++; + } + } + x++; + xerr = xFixed1 - xerr; + } + rtot += (lrtot >> 10) * yerr; + gtot += (lgtot >> 10) * yerr; + btot += (lbtot >> 10) * yerr; + atot += (latot >> 10) * yerr; + y++; + yerr = xFixed1 - yerr; + } + if ((atot >>= 22) > 0xff) atot = 0xff; + if ((rtot >>= 22) > 0xff) rtot = 0xff; + if ((gtot >>= 22) > 0xff) gtot = 0xff; + if ((btot >>= 22) > 0xff) btot = 0xff; + bits = ((atot << 24) | + (rtot << 16) | + (gtot << 8) | + (btot )); + break; + default: + bits = 0; + break; + } + return bits; +} + +FbAccessMap fbAccessMap[] = { + /* 32bpp formats */ + { PICT_a8r8g8b8, fbFetch_a8r8g8b8, fbFetch_a8r8g8b8, fbStore_a8r8g8b8 }, + { PICT_x8r8g8b8, fbFetch_x8r8g8b8, fbFetch_x8r8g8b8, fbStore_x8r8g8b8 }, + { PICT_a8b8g8r8, fbFetch_a8b8g8r8, fbFetch_a8b8g8r8, fbStore_a8b8g8r8 }, + { PICT_x8b8g8r8, fbFetch_x8b8g8r8, fbFetch_x8b8g8r8, fbStore_x8b8g8r8 }, + + /* 24bpp formats */ + { PICT_r8g8b8, fbFetch_r8g8b8, fbFetch_r8g8b8, fbStore_r8g8b8 }, + { PICT_b8g8r8, fbFetch_b8g8r8, fbFetch_b8g8r8, fbStore_b8g8r8 }, + + /* 16bpp formats */ + { PICT_r5g6b5, fbFetch_r5g6b5, fbFetch_r5g6b5, fbStore_r5g6b5 }, + { PICT_b5g6r5, fbFetch_b5g6r5, fbFetch_b5g6r5, fbStore_b5g6r5 }, + + { PICT_a1r5g5b5, fbFetch_a1r5g5b5, fbFetch_a1r5g5b5, fbStore_a1r5g5b5 }, + { PICT_x1r5g5b5, fbFetch_x1r5g5b5, fbFetch_x1r5g5b5, fbStore_x1r5g5b5 }, + { PICT_a1b5g5r5, fbFetch_a1b5g5r5, fbFetch_a1b5g5r5, fbStore_a1b5g5r5 }, + { PICT_x1b5g5r5, fbFetch_x1b5g5r5, fbFetch_x1b5g5r5, fbStore_x1b5g5r5 }, + { PICT_a4r4g4b4, fbFetch_a4r4g4b4, fbFetch_a4r4g4b4, fbStore_a4r4g4b4 }, + { PICT_x4r4g4b4, fbFetch_x4r4g4b4, fbFetch_x4r4g4b4, fbStore_x4r4g4b4 }, + { PICT_a4b4g4r4, fbFetch_a4b4g4r4, fbFetch_a4b4g4r4, fbStore_a4b4g4r4 }, + { PICT_x4b4g4r4, fbFetch_x4b4g4r4, fbFetch_x4b4g4r4, fbStore_x4b4g4r4 }, + + /* 8bpp formats */ + { PICT_a8, fbFetch_a8, fbFetcha_a8, fbStore_a8 }, + { PICT_r3g3b2, fbFetch_r3g3b2, fbFetch_r3g3b2, fbStore_r3g3b2 }, + { PICT_b2g3r3, fbFetch_b2g3r3, fbFetch_b2g3r3, fbStore_b2g3r3 }, + { PICT_a2r2g2b2, fbFetch_a2r2g2b2, fbFetch_a2r2g2b2, fbStore_a2r2g2b2 }, + { PICT_c8, fbFetch_c8, fbFetch_c8, fbStore_c8 }, + { PICT_g8, fbFetch_c8, fbFetch_c8, fbStore_g8 }, + + /* 4bpp formats */ + { PICT_a4, fbFetch_a4, fbFetcha_a4, fbStore_a4 }, + { PICT_r1g2b1, fbFetch_r1g2b1, fbFetch_r1g2b1, fbStore_r1g2b1 }, + { PICT_b1g2r1, fbFetch_b1g2r1, fbFetch_b1g2r1, fbStore_b1g2r1 }, + { PICT_a1r1g1b1, fbFetch_a1r1g1b1, fbFetch_a1r1g1b1, fbStore_a1r1g1b1 }, + { PICT_a1b1g1r1, fbFetch_a1b1g1r1, fbFetch_a1b1g1r1, fbStore_a1b1g1r1 }, + { PICT_c4, fbFetch_c4, fbFetch_c4, fbStore_c4 }, + { PICT_g4, fbFetch_c4, fbFetch_c4, fbStore_g4 }, + + /* 1bpp formats */ + { PICT_a1, fbFetch_a1, fbFetcha_a1, fbStore_a1 }, + { PICT_g1, fbFetch_g1, fbFetch_g1, fbStore_g1 }, +}; +#define NumAccessMap (sizeof fbAccessMap / sizeof fbAccessMap[0]) + +static void +fbStepOver (FbCompositeOperand *op) +{ + op->u.drawable.offset += op->u.drawable.bpp; +} + +static void +fbStepDown (FbCompositeOperand *op) +{ + op->u.drawable.line += op->u.drawable.stride; + op->u.drawable.offset = op->u.drawable.start_offset; +} + +static void +fbSet (FbCompositeOperand *op, int x, int y) +{ + op->u.drawable.line = op->u.drawable.top_line + y * op->u.drawable.stride; + op->u.drawable.offset = op->u.drawable.left_offset + x * op->u.drawable.bpp; +} + +static void +fbStepOver_external (FbCompositeOperand *op) +{ + (*op[1].over) (&op[1]); + (*op[2].over) (&op[2]); +} + +static void +fbStepDown_external (FbCompositeOperand *op) +{ + (*op[1].down) (&op[1]); + (*op[2].down) (&op[2]); +} + +static void +fbSet_external (FbCompositeOperand *op, int x, int y) +{ + (*op[1].set) (&op[1], x, y); + (*op[2].set) (&op[2], + x - op->u.external.alpha_dx, + y - op->u.external.alpha_dy); +} + +static void +fbStepOver_transform (FbCompositeOperand *op) +{ + op->u.transform.x++; +} + +static void +fbStepDown_transform (FbCompositeOperand *op) +{ + op->u.transform.y++; + op->u.transform.x = op->u.transform.start_x; +} + +static void +fbSet_transform (FbCompositeOperand *op, int x, int y) +{ + op->u.transform.x = x - op->u.transform.left_x; + op->u.transform.y = y - op->u.transform.top_y; +} + + +Bool +fbBuildCompositeOperand (PicturePtr pPict, + FbCompositeOperand op[4], + INT16 x, + INT16 y, + Bool transform, + Bool alpha) +{ + /* Check for transform */ + if (transform && pPict->transform) + { + if (!fbBuildCompositeOperand (pPict, &op[1], 0, 0, FALSE, alpha)) + return FALSE; + + op->u.transform.top_y = pPict->pDrawable->y; + op->u.transform.left_x = pPict->pDrawable->x; + + op->u.transform.start_x = x - op->u.transform.left_x; + op->u.transform.x = op->u.transform.start_x; + op->u.transform.y = y - op->u.transform.top_y; + op->u.transform.transform = pPict->transform; + op->u.transform.filter = pPict->filter; + + op->fetch = fbFetch_transform; + op->fetcha = fbFetcha_transform; + op->store = 0; + op->over = fbStepOver_transform; + op->down = fbStepDown_transform; + op->set = fbSet_transform; + op->indexed = (miIndexedPtr) pPict->pFormat->index.devPrivate; + op->clip = op[1].clip; + + return TRUE; + } + /* Check for external alpha */ + else if (alpha && pPict->alphaMap) + { + if (!fbBuildCompositeOperand (pPict, &op[1], x, y, FALSE, FALSE)) + return FALSE; + if (!fbBuildCompositeOperand (pPict->alphaMap, &op[2], + x - pPict->alphaOrigin.x, + y - pPict->alphaOrigin.y, + FALSE, FALSE)) + return FALSE; + op->u.external.alpha_dx = pPict->alphaOrigin.x; + op->u.external.alpha_dy = pPict->alphaOrigin.y; + + op->fetch = fbFetch_external; + op->fetcha = fbFetcha_external; + op->store = fbStore_external; + op->over = fbStepOver_external; + op->down = fbStepDown_external; + op->set = fbSet_external; + op->indexed = (miIndexedPtr) pPict->pFormat->index.devPrivate; + /* XXX doesn't handle external alpha clips yet */ + op->clip = op[1].clip; + + return TRUE; + } + /* Build simple operand */ + else + { + int i; + int xoff, yoff; + + for (i = 0; i < NumAccessMap; i++) + if (fbAccessMap[i].format == pPict->format) + { + FbBits *bits; + FbStride stride; + int bpp; + + op->fetch = fbAccessMap[i].fetch; + op->fetcha = fbAccessMap[i].fetcha; + op->store = fbAccessMap[i].store; + op->over = fbStepOver; + op->down = fbStepDown; + op->set = fbSet; + op->indexed = (miIndexedPtr) pPict->pFormat->index.devPrivate; + op->clip = pPict->pCompositeClip; + + fbGetDrawable (pPict->pDrawable, bits, stride, bpp, + xoff, yoff); + if (pPict->repeat && pPict->pDrawable->width == 1 && + pPict->pDrawable->height == 1) + { + bpp = 0; + stride = 0; + } + /* + * Coordinates of upper left corner of drawable + */ + op->u.drawable.top_line = bits + yoff * stride; + op->u.drawable.left_offset = xoff * bpp; + + /* + * Starting position within drawable + */ + op->u.drawable.start_offset = op->u.drawable.left_offset + x * bpp; + op->u.drawable.line = op->u.drawable.top_line + y * stride; + op->u.drawable.offset = op->u.drawable.start_offset; + + op->u.drawable.stride = stride; + op->u.drawable.bpp = bpp; + return TRUE; + } + return FALSE; + } +} + +void +fbCompositeGeneral (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + FbCompositeOperand src[4],msk[4],dst[4],*pmsk; + FbCompositeOperand *srcPict, *srcAlpha; + FbCompositeOperand *dstPict, *dstAlpha; + FbCompositeOperand *mskPict = 0, *mskAlpha = 0; + FbCombineFunc f; + int w; + + if (!fbBuildCompositeOperand (pSrc, src, xSrc, ySrc, TRUE, TRUE)) + return; + if (!fbBuildCompositeOperand (pDst, dst, xDst, yDst, FALSE, TRUE)) + return; + if (pSrc->alphaMap) + { + srcPict = &src[1]; + srcAlpha = &src[2]; + } + else + { + srcPict = &src[0]; + srcAlpha = 0; + } + if (pDst->alphaMap) + { + dstPict = &dst[1]; + dstAlpha = &dst[2]; + } + else + { + dstPict = &dst[0]; + dstAlpha = 0; + } + f = fbCombineFuncU[op]; + if (pMask) + { + if (!fbBuildCompositeOperand (pMask, msk, xMask, yMask, TRUE, TRUE)) + return; + pmsk = msk; + if (pMask->componentAlpha) + f = fbCombineFuncC[op]; + if (pMask->alphaMap) + { + mskPict = &msk[1]; + mskAlpha = &msk[2]; + } + else + { + mskPict = &msk[0]; + mskAlpha = 0; + } + } + else + pmsk = 0; + while (height--) + { + w = width; + + while (w--) + { + (*f) (src, pmsk, dst); + (*src->over) (src); + (*dst->over) (dst); + if (pmsk) + (*pmsk->over) (pmsk); + } + (*src->down) (src); + (*dst->down) (dst); + if (pmsk) + (*pmsk->down) (pmsk); + } +} diff --git a/fb/fbcopy.c b/fb/fbcopy.c new file mode 100644 index 000000000..51bc621d6 --- /dev/null +++ b/fb/fbcopy.c @@ -0,0 +1,626 @@ +/* + * Id: fbcopy.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbcopy.c,v 1.12 2001/07/16 05:04:05 keithp Exp $ */ + +#include "fb.h" +#ifdef IN_MODULE +#include "xf86_ansic.h" +#endif + +void +fbCopyNtoN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + CARD8 alu = pGC ? pGC->alu : GXcopy; + FbBits pm = pGC ? fbGetGCPrivate(pGC)->pm : FB_ALLONES; + FbBits *src; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + + fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + while (nbox--) + { + fbBlt (src + (pbox->y1 + dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff) * srcBpp, + + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + + (pbox->x2 - pbox->x1) * dstBpp, + (pbox->y2 - pbox->y1), + + alu, + pm, + dstBpp, + + reverse, + upsidedown); + pbox++; + } +} + +void +fbCopy1toN (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + FbBits *src; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + + fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + while (nbox--) + { + if (dstBpp == 1) + { + fbBlt (src + (pbox->y1 + dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff) * srcBpp, + + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + + (pbox->x2 - pbox->x1) * dstBpp, + (pbox->y2 - pbox->y1), + + FbOpaqueStipple1Rop(pGC->alu, + pGC->fgPixel,pGC->bgPixel), + pPriv->pm, + dstBpp, + + reverse, + upsidedown); + } + else + { + fbBltOne ((FbStip *) (src + (pbox->y1 + dy + srcYoff) * srcStride), + srcStride*(FB_UNIT/FB_STIP_UNIT), + (pbox->x1 + dx + srcXoff), + + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + dstBpp, + + (pbox->x2 - pbox->x1) * dstBpp, + (pbox->y2 - pbox->y1), + + pPriv->and, pPriv->xor, + pPriv->bgand, pPriv->bgxor); + } + pbox++; + } +} + +void +fbCopyNto1 (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + + while (nbox--) + { + if (pDstDrawable->bitsPerPixel == 1) + { + FbBits *src; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + + fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + fbGetStipDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + fbBltPlane (src + (pbox->y1+ dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff) * srcBpp, + srcBpp, + + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + + (pbox->x2 - pbox->x1) * srcBpp, + (pbox->y2 - pbox->y1), + + (FbStip) pPriv->and, (FbStip) pPriv->xor, + (FbStip) pPriv->bgand, (FbStip) pPriv->bgxor, + bitplane); + } + else + { + FbBits *src; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + + FbStip *tmp; + FbStride tmpStride; + int width, height; + + width = pbox->x2 - pbox->x1; + height = pbox->y2 - pbox->y1; + + tmpStride = ((width + FB_STIP_MASK) >> FB_STIP_SHIFT); + tmp = xalloc (tmpStride * height * sizeof (FbStip)); + if (!tmp) + return; + + fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + fbBltPlane (src + (pbox->y1+ dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff) * srcBpp, + srcBpp, + + tmp, + tmpStride, + 0, + + width * srcBpp, + height, + + fbAndStip(GXcopy,FB_ALLONES,FB_ALLONES), + fbXorStip(GXcopy,FB_ALLONES,FB_ALLONES), + fbAndStip(GXcopy,0,FB_ALLONES), + fbXorStip(GXcopy,0,FB_ALLONES), + bitplane); + fbBltOne (tmp, + tmpStride, + 0, + + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + dstBpp, + + width * dstBpp, + height, + + pPriv->and, pPriv->xor, + pPriv->bgand, pPriv->bgxor); + xfree (tmp); + } + pbox++; + } +} + +void +fbCopyRegion (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + RegionPtr pDstRegion, + int dx, + int dy, + fbCopyProc copyProc, + Pixel bitPlane, + void *closure) +{ + int careful; + Bool reverse; + Bool upsidedown; + BoxPtr pbox; + int nbox; + BoxPtr pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp; + + pbox = REGION_RECTS(pDstRegion); + nbox = REGION_NUM_RECTS(pDstRegion); + + /* XXX we have to err on the side of safety when both are windows, + * because we don't know if IncludeInferiors is being used. + */ + careful = ((pSrcDrawable == pDstDrawable) || + ((pSrcDrawable->type == DRAWABLE_WINDOW) && + (pDstDrawable->type == DRAWABLE_WINDOW))); + + pboxNew1 = NULL; + pboxNew2 = NULL; + if (careful && dy < 0) + { + upsidedown = TRUE; + + if (nbox > 1) + { + /* keep ordering in each band, reverse order of bands */ + pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); + if(!pboxNew1) + return; + pboxBase = pboxNext = pbox+nbox-1; + while (pboxBase >= pbox) + { + while ((pboxNext >= pbox) && + (pboxBase->y1 == pboxNext->y1)) + pboxNext--; + pboxTmp = pboxNext+1; + while (pboxTmp <= pboxBase) + { + *pboxNew1++ = *pboxTmp++; + } + pboxBase = pboxNext; + } + pboxNew1 -= nbox; + pbox = pboxNew1; + } + } + else + { + /* walk source top to bottom */ + upsidedown = FALSE; + } + + if (careful && dx < 0) + { + /* walk source right to left */ + if (dy <= 0) + reverse = TRUE; + else + reverse = FALSE; + + if (nbox > 1) + { + /* reverse order of rects in each band */ + pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); + if(!pboxNew2) + { + if (pboxNew1) + DEALLOCATE_LOCAL(pboxNew1); + return; + } + pboxBase = pboxNext = pbox; + while (pboxBase < pbox+nbox) + { + while ((pboxNext < pbox+nbox) && + (pboxNext->y1 == pboxBase->y1)) + pboxNext++; + pboxTmp = pboxNext; + while (pboxTmp != pboxBase) + { + *pboxNew2++ = *--pboxTmp; + } + pboxBase = pboxNext; + } + pboxNew2 -= nbox; + pbox = pboxNew2; + } + } + else + { + /* walk source left to right */ + reverse = FALSE; + } + + (*copyProc) (pSrcDrawable, + pDstDrawable, + pGC, + pbox, + nbox, + dx, dy, + reverse, upsidedown, bitPlane, closure); + + if (pboxNew1) + DEALLOCATE_LOCAL (pboxNew1); + if (pboxNew2) + DEALLOCATE_LOCAL (pboxNew2); +} + +RegionPtr +fbDoCopy (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, + int xOut, + int yOut, + fbCopyProc copyProc, + Pixel bitPlane, + void *closure) +{ + RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ + Bool freeSrcClip = FALSE; + RegionPtr prgnExposed = NULL; + RegionRec rgnDst; + int dx; + int dy; + int numRects; + BoxRec box; + Bool fastSrc = FALSE; /* for fast clipping with pixmap source */ + Bool fastDst = FALSE; /* for fast clipping with one rect dest */ + Bool fastExpose = FALSE; /* for fast exposures with pixmap source */ + + /* Short cut for unmapped windows */ + + if (pDstDrawable->type == DRAWABLE_WINDOW && + !((WindowPtr)pDstDrawable)->realized) + { + return NULL; + } + + if ((pSrcDrawable != pDstDrawable) && + pSrcDrawable->pScreen->SourceValidate) + { + (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn, widthSrc, heightSrc); + } + + /* Compute source clip region */ + if (pSrcDrawable->type == DRAWABLE_PIXMAP) + { + if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) + prgnSrcClip = fbGetCompositeClip(pGC); + else + fastSrc = TRUE; + } + else + { + if (pGC->subWindowMode == IncludeInferiors) + { + /* + * XFree86 DDX empties the border clip when the + * VT is inactive, make sure the region isn't empty + */ + if (!((WindowPtr) pSrcDrawable)->parent && + REGION_NOTEMPTY (pSrcDrawable->pScreen, + &((WindowPtr) pSrcDrawable)->borderClip)) + { + /* + * special case bitblt from root window in + * IncludeInferiors mode; just like from a pixmap + */ + fastSrc = TRUE; + } + else if ((pSrcDrawable == pDstDrawable) && + (pGC->clientClipType == CT_NONE)) + { + prgnSrcClip = fbGetCompositeClip(pGC); + } + else + { + prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); + freeSrcClip = TRUE; + } + } + else + { + prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; + } + } + + xIn += pSrcDrawable->x; + yIn += pSrcDrawable->y; + + xOut += pDstDrawable->x; + yOut += pDstDrawable->y; + + box.x1 = xIn; + box.y1 = yIn; + box.x2 = xIn + widthSrc; + box.y2 = yIn + heightSrc; + + dx = xIn - xOut; + dy = yIn - yOut; + + /* Don't create a source region if we are doing a fast clip */ + if (fastSrc) + { + RegionPtr cclip; + + fastExpose = TRUE; + /* + * clip the source; if regions extend beyond the source size, + * make sure exposure events get sent + */ + if (box.x1 < pSrcDrawable->x) + { + box.x1 = pSrcDrawable->x; + fastExpose = FALSE; + } + if (box.y1 < pSrcDrawable->y) + { + box.y1 = pSrcDrawable->y; + fastExpose = FALSE; + } + if (box.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) + { + box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; + fastExpose = FALSE; + } + if (box.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) + { + box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; + fastExpose = FALSE; + } + + /* Translate and clip the dst to the destination composite clip */ + box.x1 -= dx; + box.x2 -= dx; + box.y1 -= dy; + box.y2 -= dy; + + /* If the destination composite clip is one rectangle we can + do the clip directly. Otherwise we have to create a full + blown region and call intersect */ + + cclip = fbGetCompositeClip(pGC); + if (REGION_NUM_RECTS(cclip) == 1) + { + BoxPtr pBox = REGION_RECTS(cclip); + + if (box.x1 < pBox->x1) box.x1 = pBox->x1; + if (box.x2 > pBox->x2) box.x2 = pBox->x2; + if (box.y1 < pBox->y1) box.y1 = pBox->y1; + if (box.y2 > pBox->y2) box.y2 = pBox->y2; + fastDst = TRUE; + } + } + + /* Check to see if the region is empty */ + if (box.x1 >= box.x2 || box.y1 >= box.y2) + { + REGION_INIT(pGC->pScreen, &rgnDst, NullBox, 0); + } + else + { + REGION_INIT(pGC->pScreen, &rgnDst, &box, 1); + } + + /* Clip against complex source if needed */ + if (!fastSrc) + { + REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip); + REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy); + } + + /* Clip against complex dest if needed */ + if (!fastDst) + { + REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, + fbGetCompositeClip(pGC)); + } + + /* Do bit blitting */ + numRects = REGION_NUM_RECTS(&rgnDst); + if (numRects && widthSrc && heightSrc) + fbCopyRegion (pSrcDrawable, pDstDrawable, pGC, + &rgnDst, dx, dy, copyProc, bitPlane, closure); + + /* Pixmap sources generate a NoExposed (we return NULL to do this) */ + if (!fastExpose && pGC->fExpose) + prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + xIn - pSrcDrawable->x, + yIn - pSrcDrawable->y, + widthSrc, heightSrc, + xOut - pDstDrawable->x, + yOut - pDstDrawable->y, + (unsigned long) bitPlane); + REGION_UNINIT(pGC->pScreen, &rgnDst); + if (freeSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + fbValidateDrawable (pDstDrawable); + return prgnExposed; +} + +RegionPtr +fbCopyArea (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, + int xOut, + int yOut) +{ + fbCopyProc copy; + +#ifdef FB_24_32BIT + if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel) + copy = fb24_32CopyMtoN; + else +#endif + copy = fbCopyNtoN; + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, xIn, yIn, + widthSrc, heightSrc, xOut, yOut, copy, 0, 0); +} + +RegionPtr +fbCopyPlane (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + int xIn, + int yIn, + int widthSrc, + int heightSrc, + int xOut, + int yOut, + unsigned long bitplane) +{ + if (pSrcDrawable->bitsPerPixel > 1) + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, + xIn, yIn, widthSrc, heightSrc, + xOut, yOut, fbCopyNto1, (Pixel) bitplane, 0); + else if (bitplane & 1) + return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, xIn, yIn, + widthSrc, heightSrc, xOut, yOut, fbCopy1toN, + (Pixel) bitplane, 0); + else + return miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + xIn, yIn, + widthSrc, + heightSrc, + xOut, yOut, bitplane); +} diff --git a/fb/fbfill.c b/fb/fbfill.c new file mode 100644 index 000000000..8ecb3cde6 --- /dev/null +++ b/fb/fbfill.c @@ -0,0 +1,212 @@ +/* + * Id: fbfill.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbfill.c,v 1.6 2003/01/31 00:01:45 torrey Exp $ */ + +#include "fb.h" + +void +fbFill (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + int width, + int height) +{ + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + switch (pGC->fillStyle) { + case FillSolid: + fbSolid (dst + (y + dstYoff) * dstStride, + dstStride, + (x + dstXoff) * dstBpp, + dstBpp, + width * dstBpp, height, + pPriv->and, pPriv->xor); + break; + case FillStippled: + case FillOpaqueStippled: { + PixmapPtr pStip = pGC->stipple; + int stipWidth = pStip->drawable.width; + int stipHeight = pStip->drawable.height; + + if (dstBpp == 1) + { + int alu; + FbBits *stip; + FbStride stipStride; + int stipBpp; + int stipXoff, stipYoff; /* XXX assumed to be zero */ + + if (pGC->fillStyle == FillStippled) + alu = FbStipple1Rop(pGC->alu,pGC->fgPixel); + else + alu = FbOpaqueStipple1Rop(pGC->alu,pGC->fgPixel,pGC->bgPixel); + fbGetDrawable (&pStip->drawable, stip, stipStride, stipBpp, stipXoff, stipYoff); + fbTile (dst + (y + dstYoff) * dstStride, + dstStride, + x + dstXoff, + width, height, + stip, + stipStride, + stipWidth, + stipHeight, + alu, + pPriv->pm, + dstBpp, + + (pGC->patOrg.x + pDrawable->x + dstXoff), + pGC->patOrg.y + pDrawable->y + dstYoff - y); + } + else + { + FbStip *stip; + FbStride stipStride; + int stipBpp; + int stipXoff, stipYoff; /* XXX assumed to be zero */ + FbBits fgand, fgxor, bgand, bgxor; + + fgand = pPriv->and; + fgxor = pPriv->xor; + if (pGC->fillStyle == FillStippled) + { + bgand = fbAnd(GXnoop,(FbBits) 0,FB_ALLONES); + bgxor = fbXor(GXnoop,(FbBits) 0,FB_ALLONES); + } + else + { + bgand = pPriv->bgand; + bgxor = pPriv->bgxor; + } + + fbGetStipDrawable (&pStip->drawable, stip, stipStride, stipBpp, stipXoff, stipYoff); + fbStipple (dst + (y + dstYoff) * dstStride, + dstStride, + (x + dstXoff) * dstBpp, + dstBpp, + width * dstBpp, height, + stip, + stipStride, + stipWidth, + stipHeight, + pPriv->evenStipple, + fgand, fgxor, + bgand, bgxor, + pGC->patOrg.x + pDrawable->x + dstXoff, + pGC->patOrg.y + pDrawable->y + dstYoff - y); + } + break; + } + case FillTiled: { + PixmapPtr pTile = pGC->tile.pixmap; + FbBits *tile; + FbStride tileStride; + int tileBpp; + int tileWidth; + int tileHeight; + int tileXoff, tileYoff; /* XXX assumed to be zero */ + + fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp, tileXoff, tileYoff); + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + fbTile (dst + (y + dstYoff) * dstStride, + dstStride, + (x + dstXoff) * dstBpp, + width * dstBpp, height, + tile, + tileStride, + tileWidth * tileBpp, + tileHeight, + pGC->alu, + pPriv->pm, + dstBpp, + (pGC->patOrg.x + pDrawable->x + dstXoff) * dstBpp, + pGC->patOrg.y + pDrawable->y + dstYoff - y); + break; + } + } + fbValidateDrawable (pDrawable); +} + +void +fbSolidBoxClipped (DrawablePtr pDrawable, + RegionPtr pClip, + int x1, + int y1, + int x2, + int y2, + FbBits and, + FbBits xor) +{ + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + BoxPtr pbox; + int nbox; + int partX1, partX2, partY1, partY2; + + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + 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; + + fbSolid (dst + (partY1 + dstYoff) * dstStride, + dstStride, + (partX1 + dstXoff) * dstBpp, + dstBpp, + + (partX2 - partX1) * dstBpp, + (partY2 - partY1), + and, xor); + } +} diff --git a/fb/fbfillrect.c b/fb/fbfillrect.c new file mode 100644 index 000000000..d0468e041 --- /dev/null +++ b/fb/fbfillrect.c @@ -0,0 +1,111 @@ +/* + * Id: fbfillrect.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbfillrect.c,v 1.2 2000/02/23 20:29:43 dawes Exp $ */ + +#include "fb.h" + +void +fbPolyFillRect(DrawablePtr pDrawable, + GCPtr pGC, + int nrect, + xRectangle *prect) +{ + RegionPtr pClip = fbGetCompositeClip(pGC); + register BoxPtr pbox; + BoxPtr pextent; + int extentX1, extentX2, extentY1, extentY2; + int fullX1, fullX2, fullY1, fullY2; + int partX1, partX2, partY1, partY2; + int xorg, yorg; + int n; + + xorg = pDrawable->x; + yorg = pDrawable->y; + + pextent = REGION_EXTENTS(pGC->pScreen, pClip); + extentX1 = pextent->x1; + extentY1 = pextent->y1; + extentX2 = pextent->x2; + extentY2 = pextent->y2; + while (nrect--) + { + fullX1 = prect->x + xorg; + fullY1 = prect->y + yorg; + fullX2 = fullX1 + (int) prect->width; + fullY2 = fullY1 + (int) prect->height; + prect++; + + if (fullX1 < extentX1) + fullX1 = extentX1; + + if (fullY1 < extentY1) + fullY1 = extentY1; + + if (fullX2 > extentX2) + fullX2 = extentX2; + + if (fullY2 > extentY2) + fullY2 = extentY2; + + if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) + continue; + n = REGION_NUM_RECTS (pClip); + if (n == 1) + { + fbFill (pDrawable, + pGC, + fullX1, fullY1, fullX2-fullX1, fullY2-fullY1); + } + else + { + pbox = REGION_RECTS(pClip); + /* + * clip the rectangle to each box in the clip region + * this is logically equivalent to calling Intersect() + */ + while(n--) + { + partX1 = pbox->x1; + if (partX1 < fullX1) + partX1 = fullX1; + partY1 = pbox->y1; + if (partY1 < fullY1) + partY1 = fullY1; + partX2 = pbox->x2; + if (partX2 > fullX2) + partX2 = fullX2; + partY2 = pbox->y2; + if (partY2 > fullY2) + partY2 = fullY2; + + pbox++; + + if (partX1 < partX2 && partY1 < partY2) + fbFill (pDrawable, pGC, + partX1, partY1, + partX2 - partX1, partY2 - partY1); + } + } + } +} diff --git a/fb/fbfillsp.c b/fb/fbfillsp.c new file mode 100644 index 000000000..29c3a36b0 --- /dev/null +++ b/fb/fbfillsp.c @@ -0,0 +1,99 @@ +/* + * Id: fbfillsp.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbfillsp.c,v 1.2 2000/02/23 20:29:43 dawes Exp $ */ + +#include "fb.h" + +void +fbFillSpans (DrawablePtr pDrawable, + GCPtr pGC, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted) +{ + RegionPtr pClip = fbGetCompositeClip(pGC); + BoxPtr pextent, pbox; + int nbox; + int extentX1, extentX2, extentY1, extentY2; + int fullX1, fullX2, fullY1; + int partX1, partX2; + + pextent = REGION_EXTENTS(pGC->pScreen, pClip); + extentX1 = pextent->x1; + extentY1 = pextent->y1; + extentX2 = pextent->x2; + extentY2 = pextent->y2; + while (n--) + { + fullX1 = ppt->x; + fullY1 = ppt->y; + fullX2 = fullX1 + (int) *pwidth; + ppt++; + pwidth++; + + if (fullY1 < extentY1 || extentY2 <= fullY1) + continue; + + if (fullX1 < extentX1) + fullX1 = extentX1; + + if (fullX2 > extentX2) + fullX2 = extentX2; + + if (fullX1 >= fullX2) + continue; + + nbox = REGION_NUM_RECTS (pClip); + if (nbox == 1) + { + fbFill (pDrawable, + pGC, + fullX1, fullY1, fullX2-fullX1, 1); + } + else + { + pbox = REGION_RECTS(pClip); + while(nbox--) + { + if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) + { + partX1 = pbox->x1; + if (partX1 < fullX1) + partX1 = fullX1; + partX2 = pbox->x2; + if (partX2 > fullX2) + partX2 = fullX2; + if (partX2 > partX1) + { + fbFill (pDrawable, pGC, + partX1, fullY1, + partX2 - partX1, 1); + } + } + pbox++; + } + } + } +} diff --git a/fb/fbgc.c b/fb/fbgc.c new file mode 100644 index 000000000..28c58a673 --- /dev/null +++ b/fb/fbgc.c @@ -0,0 +1,310 @@ +/* + * Id: fbgc.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbgc.c,v 1.12 2001/05/29 04:54:09 keithp Exp $ */ + +#include "fb.h" +#ifdef IN_MODULE +#include "xf86_ansic.h" +#endif + +const GCFuncs fbGCFuncs = { + fbValidateGC, + miChangeGC, + miCopyGC, + miDestroyGC, + miChangeClip, + miDestroyClip, + miCopyClip, +}; + +const GCOps fbGCOps = { + fbFillSpans, + fbSetSpans, + fbPutImage, + fbCopyArea, + fbCopyPlane, + fbPolyPoint, + fbPolyLine, + fbPolySegment, + fbPolyRectangle, + fbPolyArc, + miFillPolygon, + fbPolyFillRect, + fbPolyFillArc, + miPolyText8, + miPolyText16, + miImageText8, + miImageText16, + fbImageGlyphBlt, + fbPolyGlyphBlt, + fbPushPixels +#ifdef NEED_LINEHELPER + ,NULL +#endif +}; + +Bool +fbCreateGC(GCPtr pGC) +{ + pGC->clientClip = NULL; + pGC->clientClipType = CT_NONE; + + pGC->ops = (GCOps *) &fbGCOps; + pGC->funcs = (GCFuncs *) &fbGCFuncs; + + /* fb wants to translate before scan conversion */ + pGC->miTranslate = 1; + + fbGetRotatedPixmap(pGC) = 0; + fbGetExpose(pGC) = 1; + fbGetFreeCompClip(pGC) = 0; + fbGetCompositeClip(pGC) = 0; + fbGetGCPrivate(pGC)->bpp = BitsPerPixel (pGC->depth); + return TRUE; +} + +/* + * Pad pixmap to FB_UNIT bits wide + */ +void +fbPadPixmap (PixmapPtr pPixmap) +{ + int width; + FbBits *bits; + FbBits b; + FbBits mask; + int height; + int w; + + width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel; + bits = pPixmap->devPrivate.ptr; + height = pPixmap->drawable.height; + mask = FbBitsMask (0, width); + while (height--) + { + b = *bits & mask; + w = width; + while (w < FB_UNIT) + { + b = b | FbScrRight(b, w); + w <<= 1; + } + *bits++ = b; + } +} + +/* + * Verify that 'bits' repeats every 'len' bits + */ +static Bool +fbBitsRepeat (FbBits bits, int len, int width) +{ + FbBits mask = FbBitsMask(0, len); + FbBits orig = bits & mask; + int i; + + if (width > FB_UNIT) + width = FB_UNIT; + for (i = 0; i < width / len; i++) + { + if ((bits & mask) != orig) + return FALSE; + bits = FbScrLeft(bits,len); + } + return TRUE; +} + +/* + * Check whether an entire bitmap line is a repetition of + * the first 'len' bits + */ +static Bool +fbLineRepeat (FbBits *bits, int len, int width) +{ + FbBits first = bits[0]; + + if (!fbBitsRepeat (first, len, width)) + return FALSE; + width = (width + FB_UNIT-1) >> FB_SHIFT; + bits++; + while (--width) + if (*bits != first) + return FALSE; + return TRUE; +} + +/* + * The even stipple code wants the first FB_UNIT/bpp bits on + * each scanline to represent the entire stipple + */ +static Bool +fbCanEvenStipple (PixmapPtr pStipple, int bpp) +{ + int len = FB_UNIT / bpp; + FbBits *bits; + int stride; + int stip_bpp; + int stipXoff, stipYoff; + int h; + + /* can't even stipple 24bpp drawables */ + if ((bpp & (bpp-1)) != 0) + return FALSE; + /* make sure the stipple width is a multiple of the even stipple width */ + if (pStipple->drawable.width % len != 0) + return FALSE; + fbGetDrawable (&pStipple->drawable, bits, stride, stip_bpp, stipXoff, stipYoff); + h = pStipple->drawable.height; + /* check to see that the stipple repeats horizontally */ + while (h--) + { + if (!fbLineRepeat (bits, len, pStipple->drawable.width)) + return FALSE; + bits += stride; + } + return TRUE; +} + +void +fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + FbBits mask; + + pGC->lastWinOrg.x = pDrawable->x; + pGC->lastWinOrg.y = pDrawable->y; + + /* + * if the client clip is different or moved OR the subwindowMode has + * changed OR the window's clip has changed since the last validation + * we need to recompute the composite clip + */ + + if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) || + (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) + ) + { + miComputeCompositeClip (pGC, pDrawable); + pPriv->oneRect = REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1; + } + +#ifdef FB_24_32BIT + if (pPriv->bpp != pDrawable->bitsPerPixel) + { + changes |= GCStipple|GCForeground|GCBackground|GCPlaneMask; + pPriv->bpp = pDrawable->bitsPerPixel; + } + if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) + { + (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); + fbGetRotatedPixmap(pGC) = 0; + } + + if (pGC->fillStyle == FillTiled) + { + PixmapPtr pOldTile, pNewTile; + + pOldTile = pGC->tile.pixmap; + if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) + { + pNewTile = fbGetRotatedPixmap(pGC); + if (!pNewTile || pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel) + { + if (pNewTile) + (*pGC->pScreen->DestroyPixmap) (pNewTile); + pNewTile = fb24_32ReformatTile (pOldTile, pDrawable->bitsPerPixel); + } + if (pNewTile) + { + fbGetRotatedPixmap(pGC) = pOldTile; + pGC->tile.pixmap = pNewTile; + changes |= GCTile; + } + } + } +#endif + if (changes & GCTile) + { + if (!pGC->tileIsPixel && + FbEvenTile (pGC->tile.pixmap->drawable.width * + pDrawable->bitsPerPixel)) + fbPadPixmap (pGC->tile.pixmap); + } + if (changes & GCStipple) + { + if (pGC->stipple && + (FbEvenStip (pGC->stipple->drawable.width, + pDrawable->bitsPerPixel) || + fbCanEvenStipple (pGC->stipple, pDrawable->bitsPerPixel))) + { + pPriv->evenStipple = TRUE; + if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel < FB_UNIT) + fbPadPixmap (pGC->stipple); + } + else + pPriv->evenStipple = FALSE; + } + /* + * Recompute reduced rop values + */ + if (changes & (GCForeground|GCBackground|GCPlaneMask|GCFunction)) + { + int s; + FbBits depthMask; + + mask = FbFullMask(pDrawable->bitsPerPixel); + depthMask = FbFullMask(pDrawable->depth); + + pPriv->fg = pGC->fgPixel & mask; + pPriv->bg = pGC->bgPixel & mask; + + if ((pGC->planemask & depthMask) == depthMask) + pPriv->pm = mask; + else + pPriv->pm = pGC->planemask & mask; + + s = pDrawable->bitsPerPixel; + while (s < FB_UNIT) + { + pPriv->fg |= pPriv->fg << s; + pPriv->bg |= pPriv->bg << s; + pPriv->pm |= pPriv->pm << s; + s <<= 1; + } + pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm); + pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm); + pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm); + pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm); + } + if (changes & GCDashList) + { + unsigned short n = pGC->numInDashList; + unsigned char *dash = pGC->dash; + unsigned int dashLength = 0; + + while (n--) + dashLength += (unsigned int ) *dash++; + pPriv->dashLength = dashLength; + } +} diff --git a/fb/fbgetsp.c b/fb/fbgetsp.c new file mode 100644 index 000000000..db35f6d5c --- /dev/null +++ b/fb/fbgetsp.c @@ -0,0 +1,84 @@ +/* + * Id: fbgetsp.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbgetsp.c,v 1.6 2001/05/29 04:54:09 keithp Exp $ */ + +#include "fb.h" + +void +fbGetSpans(DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, + int *pwidth, + int nspans, + char *pchardstStart) +{ + FbBits *src, *dst; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + int xoff; + + /* + * XFree86 DDX empties the root borderClip when the VT is + * switched away; this checks for that case + */ + if (!fbDrawableEnabled(pDrawable)) + return; + +#ifdef FB_24_32BIT + if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) + { + fb24_32GetSpans (pDrawable, wMax, ppt, pwidth, nspans, pchardstStart); + return; + } +#endif + + fbGetDrawable (pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + + while (nspans--) + { + xoff = (int) (((long) pchardstStart) & (FB_MASK >> 3)); + dst = (FbBits *) (pchardstStart - xoff); + xoff <<= 3; + fbBlt (src + (ppt->y + srcYoff) * srcStride, srcStride, + (ppt->x + srcXoff) * srcBpp, + + dst, + 1, + xoff, + + *pwidth * srcBpp, + 1, + + GXcopy, + FB_ALLONES, + srcBpp, + + FALSE, + FALSE); + pchardstStart += PixmapBytePad(*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } +} diff --git a/fb/fbglyph.c b/fb/fbglyph.c new file mode 100644 index 000000000..f8f2179d5 --- /dev/null +++ b/fb/fbglyph.c @@ -0,0 +1,472 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fbglyph.c,v 1.12 2001/09/07 15:16:00 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. + */ + +#include "fb.h" +#include "fontstruct.h" +#include "dixfontstr.h" + +Bool +fbGlyphIn (RegionPtr pRegion, + int x, + int y, + int width, + int height) +{ + BoxRec box; + BoxPtr pExtents = REGION_EXTENTS (0, pRegion); + + /* + * Check extents by hand to avoid 16 bit overflows + */ + if (x < (int) pExtents->x1) + return FALSE; + if ((int) pExtents->x2 < x + width) + return FALSE; + if (y < (int) pExtents->y1) + return FALSE; + if ((int) pExtents->y2 < y + height) + return FALSE; + box.x1 = x; + box.x2 = x + width; + box.y1 = y; + box.y2 = y + height; + return RECT_IN_REGION (0, pRegion, &box) == rgnIN; +} + +#ifdef FB_24BIT +#ifndef FBNOPIXADDR + +#define WRITE1(d,n,fg) ((d)[n] = (CARD8) fg) +#define WRITE2(d,n,fg) (*(CARD16 *) &(d[n]) = (CARD16) fg) +#define WRITE4(d,n,fg) (*(CARD32 *) &(d[n]) = (CARD32) fg) +#if FB_UNIT == 6 && IMAGE_BYTE_ORDER == LSBFirst +#define WRITE8(d) (*(FbBits *) &(d[0]) = fg) +#else +#define WRITE8(d) WRITE4(d,0,_ABCA), WRITE4(d,4,_BCAB) +#endif + +/* + * This is a bit tricky, but it's brief. Write 12 bytes worth + * of dest, which is four pixels, at a time. This gives constant + * code for each pattern as they're always aligned the same + * + * a b c d a b c d a b c d bytes + * A B C A B C A B C A B C pixels + * + * f0 f1 f2 + * A B C A B C A B C A B C pixels LSB + * C A B C A B C A B C A B pixels MSB + * + * LSB MSB + * A f0 f1 + * B f1 f2 + * C f2 f0 + * A B f0 f2 + * B C f1 f0 + * C A f2 f1 + * A B C A f0 f1 + * B C A B f1 f2 + * C A B C f2 f0 + */ + +#undef _A +#undef _B +#undef _C +#undef _AB +#undef _BC +#undef _CA +#undef _ABCA +#undef _BCAB +#undef _CABC + +#if IMAGE_BYTE_ORDER == MSBFirst +#define _A f1 +#define _B f2 +#define _C f0 +#define _AB f2 +#define _BC f0 +#define _CA f1 +#define _ABCA f1 +#define _BCAB f2 +#define _CABC f0 +#define CASE(a,b,c,d) ((a << 3) | (b << 2) | (c << 1) | d) +#else +#define _A f0 +#define _B f1 +#define _C f2 +#define _AB f0 +#define _BC f1 +#define _CA f2 +#define _ABCA f0 +#define _BCAB f1 +#define _CABC f2 +#define CASE(a,b,c,d) (a | (b << 1) | (c << 2) | (d << 3)) +#endif + +void +fbGlyph24 (FbBits *dstBits, + FbStride dstStride, + int dstBpp, + FbStip *stipple, + FbBits fg, + int x, + int height) +{ + int lshift; + FbStip bits; + CARD8 *dstLine; + CARD8 *dst; + FbStip f0, f1, f2; + int n; + int shift; + + f0 = fg; + f1 = FbRot24(f0,16); + f2 = FbRot24(f0,8); + + dstLine = (CARD8 *) dstBits; + dstLine += (x & ~3) * 3; + dstStride *= (sizeof (FbBits) / sizeof (CARD8)); + shift = x & 3; + lshift = 4 - shift; + while (height--) + { + bits = *stipple++; + n = lshift; + dst = dstLine; + while (bits) + { + switch (FbStipMoveLsb (FbLeftStipBits (bits, n), 4, n)) { + case CASE(0,0,0,0): + break; + case CASE(1,0,0,0): + WRITE2(dst,0,_AB); + WRITE1(dst,2,_C); + break; + case CASE(0,1,0,0): + WRITE1(dst,3,_A); + WRITE2(dst,4,_BC); + break; + case CASE(1,1,0,0): + WRITE4(dst,0,_ABCA); + WRITE2(dst,4,_BC); + break; + case CASE(0,0,1,0): + WRITE2(dst,6,_AB); + WRITE1(dst,8,_C); + break; + case CASE(1,0,1,0): + WRITE2(dst,0,_AB); + WRITE1(dst,2,_C); + + WRITE2(dst,6,_AB); + WRITE1(dst,8,_C); + break; + case CASE(0,1,1,0): + WRITE1(dst,3,_A); + WRITE4(dst,4,_BCAB); + WRITE1(dst,8,_C); + break; + case CASE(1,1,1,0): + WRITE8(dst); + WRITE1(dst,8,_C); + break; + case CASE(0,0,0,1): + WRITE1(dst,9,_A); + WRITE2(dst,10,_BC); + break; + case CASE(1,0,0,1): + WRITE2(dst,0,_AB); + WRITE1(dst,2,_C); + + WRITE1(dst,9,_A); + WRITE2(dst,10,_BC); + break; + case CASE(0,1,0,1): + WRITE1(dst,3,_A); + WRITE2(dst,4,_BC); + + WRITE1(dst,9,_A); + WRITE2(dst,10,_BC); + break; + case CASE(1,1,0,1): + WRITE4(dst,0,_ABCA); + WRITE2(dst,4,_BC); + + WRITE1(dst,9,_A); + WRITE2(dst,10,_BC); + break; + case CASE(0,0,1,1): + WRITE2(dst,6,_AB); + WRITE4(dst,8,_CABC); + break; + case CASE(1,0,1,1): + WRITE2(dst,0,_AB); + WRITE1(dst,2,_C); + + WRITE2(dst,6,_AB); + WRITE4(dst,8,_CABC); + break; + case CASE(0,1,1,1): + WRITE1(dst,3,_A); + WRITE4(dst,4,_BCAB); + WRITE4(dst,8,_CABC); + break; + case CASE(1,1,1,1): + WRITE8(dst); + WRITE4(dst,8,_CABC); + break; + } + bits = FbStipLeft (bits, n); + n = 4; + dst += 12; + } + dstLine += dstStride; + } +} +#endif +#endif + +void +fbPolyGlyphBlt (DrawablePtr pDrawable, + GCPtr pGC, + int x, + int y, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + CharInfoPtr pci; + unsigned char *pglyph; /* pointer bits in glyph */ + int gx, gy; + int gWidth, gHeight; /* width and height of glyph */ + FbStride gStride; /* stride of glyph */ +#ifndef FBNOPIXADDR + void (*glyph) (FbBits *, + FbStride, + int, + FbStip *, + FbBits, + int, + int); + FbBits *dst = 0; + FbStride dstStride = 0; + int dstBpp = 0; + int dstXoff = 0, dstYoff = 0; + + glyph = 0; + if (pGC->fillStyle == FillSolid && pPriv->and == 0) + { + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + switch (dstBpp) { + case 8: glyph = fbGlyph8; break; + case 16: glyph = fbGlyph16; break; +#ifdef FB_24BIT + case 24: glyph = fbGlyph24; break; +#endif + case 32: glyph = fbGlyph32; break; + } + } +#endif + x += pDrawable->x; + y += pDrawable->y; + + 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; +#ifndef FBNOPIXADDR + if (glyph && gWidth <= sizeof (FbStip) * 8 && + fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) + { + (*glyph) (dst + (gy + dstYoff) * dstStride, + dstStride, + dstBpp, + (FbStip *) pglyph, + pPriv->xor, + gx + dstXoff, + gHeight); + } + else +#endif + { + gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); + fbPushImage (pDrawable, + pGC, + + (FbStip *) pglyph, + gStride, + 0, + + gx, + gy, + gWidth, gHeight); + } + } + x += pci->metrics.characterWidth; + } +} + + +void +fbImageGlyphBlt (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; +#ifndef FBNOPIXADDR + void (*glyph) (FbBits *, + FbStride, + int, + FbStip *, + FbBits, + int, + int); + FbBits *dst = 0; + FbStride dstStride = 0; + int dstBpp = 0; + int dstXoff = 0, dstYoff = 0; + + glyph = 0; + if (pPriv->and == 0) + { + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + switch (dstBpp) { + case 8: glyph = fbGlyph8; break; + case 16: glyph = fbGlyph16; break; +#ifdef FB_24BIT + case 24: glyph = fbGlyph24; break; +#endif + case 32: glyph = fbGlyph32; break; + } + } +#endif + + x += pDrawable->x; + y += pDrawable->y; + + if (TERMINALFONT (pGC->font) +#ifndef FBNOPIXADDR + && !glyph +#endif + ) + { + opaque = TRUE; + } + else + { + int xBack, widthBack; + int yBack, heightBack; + + 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); + fbSolidBoxClipped (pDrawable, + fbGetCompositeClip(pGC), + xBack, + yBack, + xBack + widthBack, + yBack + heightBack, + fbAnd(GXcopy,pPriv->bg,pPriv->pm), + fbXor(GXcopy,pPriv->bg,pPriv->pm)); + opaque = FALSE; + } + + 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; +#ifndef FBNOPIXADDR + if (glyph && gWidth <= sizeof (FbStip) * 8 && + fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) + { + (*glyph) (dst + (gy + dstYoff) * dstStride, + dstStride, + dstBpp, + (FbStip *) pglyph, + pPriv->fg, + gx + dstXoff, + gHeight); + } + else +#endif + { + gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); + fbPutXYImage (pDrawable, + fbGetCompositeClip(pGC), + pPriv->fg, + pPriv->bg, + pPriv->pm, + GXcopy, + opaque, + + gx, + gy, + gWidth, gHeight, + + (FbStip *) pglyph, + gStride, + 0); + } + } + x += pci->metrics.characterWidth; + } +} diff --git a/fb/fbimage.c b/fb/fbimage.c new file mode 100644 index 000000000..7d0284c38 --- /dev/null +++ b/fb/fbimage.c @@ -0,0 +1,364 @@ +/* + * Id: fbimage.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbimage.c,v 1.8 2001/09/07 15:15:31 keithp Exp $ */ + +#include "fb.h" +#ifdef XFree86LOADER +#include "xf86.h" +#include "xf86_ansic.h" +#endif + + +void +fbPutImage (DrawablePtr pDrawable, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + unsigned long i; + FbStride srcStride; + FbStip *src = (FbStip *) pImage; + + x += pDrawable->x; + y += pDrawable->y; + + switch (format) + { + case XYBitmap: + srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip); + fbPutXYImage (pDrawable, + fbGetCompositeClip(pGC), + pPriv->fg, + pPriv->bg, + pPriv->pm, + pGC->alu, + TRUE, + x, y, w, h, + src, + srcStride, + leftPad); + break; + case XYPixmap: + srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip); + for (i = 1 << (pDrawable->depth - 1); i; i >>= 1) + { + if (i & pGC->planemask) + { + fbPutXYImage (pDrawable, + fbGetCompositeClip(pGC), + FB_ALLONES, + 0, + fbReplicatePixel (i, pDrawable->bitsPerPixel), + pGC->alu, + TRUE, + x, y, w, h, + src, + srcStride, + leftPad); + src += srcStride * h; + } + } + break; + case ZPixmap: +#ifdef FB_24_32BIT + if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) + { + srcStride = PixmapBytePad(w, pDrawable->depth); + fb24_32PutZImage (pDrawable, + fbGetCompositeClip(pGC), + pGC->alu, + (FbBits) pGC->planemask, + x, y, w, h, + (CARD8 *) pImage, + srcStride); + } + else +#endif + { + srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof (FbStip); + fbPutZImage (pDrawable, + fbGetCompositeClip(pGC), + pGC->alu, + pPriv->pm, + x, y, w, h, + src, srcStride); + } + } +} + +void +fbPutZImage (DrawablePtr pDrawable, + RegionPtr pClip, + int alu, + FbBits pm, + int x, + int y, + int width, + int height, + FbStip *src, + FbStride srcStride) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + int nbox; + BoxPtr pbox; + int x1, y1, x2, y2; + + fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + for (nbox = REGION_NUM_RECTS (pClip), + pbox = REGION_RECTS(pClip); + nbox--; + pbox++) + { + x1 = x; + y1 = y; + x2 = x + width; + y2 = y + height; + if (x1 < pbox->x1) + x1 = pbox->x1; + if (y1 < pbox->y1) + y1 = pbox->y1; + if (x2 > pbox->x2) + x2 = pbox->x2; + if (y2 > pbox->y2) + y2 = pbox->y2; + if (x1 >= x2 || y1 >= y2) + continue; + fbBltStip (src + (y1 - y) * srcStride, + srcStride, + (x1 - x) * dstBpp, + + dst + (y1 + dstYoff) * dstStride, + dstStride, + (x1 + dstXoff) * dstBpp, + + (x2 - x1) * dstBpp, + (y2 - y1), + + alu, + pm, + dstBpp); + } +} + +void +fbPutXYImage (DrawablePtr pDrawable, + RegionPtr pClip, + FbBits fg, + FbBits bg, + FbBits pm, + int alu, + Bool opaque, + + int x, + int y, + int width, + int height, + + FbStip *src, + FbStride srcStride, + int srcX) +{ + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + int nbox; + BoxPtr pbox; + int x1, y1, x2, y2; + FbBits fgand = 0, fgxor = 0, bgand = 0, bgxor = 0; + + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + if (dstBpp == 1) + { + if (opaque) + alu = FbOpaqueStipple1Rop(alu,fg,bg); + else + alu = FbStipple1Rop(alu,fg); + } + else + { + fgand = fbAnd(alu,fg,pm); + fgxor = fbXor(alu,fg,pm); + if (opaque) + { + bgand = fbAnd(alu,bg,pm); + bgxor = fbXor(alu,bg,pm); + } + else + { + bgand = fbAnd(GXnoop,(FbBits)0,FB_ALLONES); + bgxor = fbXor(GXnoop,(FbBits)0,FB_ALLONES); + } + } + + for (nbox = REGION_NUM_RECTS (pClip), + pbox = REGION_RECTS(pClip); + nbox--; + pbox++) + { + x1 = x; + y1 = y; + x2 = x + width; + y2 = y + height; + if (x1 < pbox->x1) + x1 = pbox->x1; + if (y1 < pbox->y1) + y1 = pbox->y1; + if (x2 > pbox->x2) + x2 = pbox->x2; + if (y2 > pbox->y2) + y2 = pbox->y2; + if (x1 >= x2 || y1 >= y2) + continue; + if (dstBpp == 1) + { + fbBltStip (src + (y1 - y) * srcStride, + srcStride, + (x1 - x) + srcX, + + (FbStip *) (dst + (y1 + dstYoff) * dstStride), + FbBitsStrideToStipStride(dstStride), + (x1 + dstXoff) * dstBpp, + + (x2 - x1) * dstBpp, + (y2 - y1), + + alu, + pm, + dstBpp); + } + else + { + fbBltOne (src + (y1 - y) * srcStride, + srcStride, + (x1 - x) + srcX, + + dst + (y1 + dstYoff) * dstStride, + dstStride, + (x1 + dstXoff) * dstBpp, + dstBpp, + + (x2 - x1) * dstBpp, + (y2 - y1), + + fgand, fgxor, bgand, bgxor); + } + } +} + +void +fbGetImage (DrawablePtr pDrawable, + int x, + int y, + int w, + int h, + unsigned int format, + unsigned long planeMask, + char *d) +{ + FbBits *src; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + FbStip *dst; + FbStride dstStride; + + /* + * XFree86 DDX empties the root borderClip when the VT is + * switched away; this checks for that case + */ + if (!fbDrawableEnabled(pDrawable)) + return; + +#ifdef FB_24_32BIT + if (format == ZPixmap && + pDrawable->bitsPerPixel != BitsPerPixel (pDrawable->depth)) + { + fb24_32GetImage (pDrawable, x, y, w, h, format, planeMask, d); + return; + } +#endif + + fbGetDrawable (pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + + x += pDrawable->x; + y += pDrawable->y; + + dst = (FbStip *) d; + if (format == ZPixmap || srcBpp == 1) + { + FbBits pm; + + pm = fbReplicatePixel (planeMask, srcBpp); + dstStride = PixmapBytePad(w, pDrawable->depth); + if (pm != FB_ALLONES) + memset (d, 0, dstStride * h); + dstStride /= sizeof (FbStip); + fbBltStip ((FbStip *) (src + (y + srcYoff) * srcStride), + FbBitsStrideToStipStride(srcStride), + (x + srcXoff) * srcBpp, + + dst, + dstStride, + 0, + + w * srcBpp, h, + + GXcopy, + pm, + srcBpp); + } + else + { + dstStride = BitmapBytePad(w) / sizeof (FbStip); + fbBltPlane (src + (y + srcYoff) * srcStride, + srcStride, + (x + srcXoff) * srcBpp, + srcBpp, + + dst, + dstStride, + 0, + + w * srcBpp, h, + + fbAndStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES), + fbXorStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES), + fbAndStip(GXcopy,0,FB_STIP_ALLONES), + fbXorStip(GXcopy,0,FB_STIP_ALLONES), + planeMask); + } +} diff --git a/fb/fbline.c b/fb/fbline.c new file mode 100644 index 000000000..b6cf1c84b --- /dev/null +++ b/fb/fbline.c @@ -0,0 +1,179 @@ +/* + * Id: fbline.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbline.c,v 1.7 2001/01/17 07:40:02 keithp Exp $ */ + +#include "fb.h" + +void +fbZeroLine (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ppt) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + int x1, y1, x2, y2; + int x, y; + int dashOffset; + int totalDash; + + x = pDrawable->x; + y = pDrawable->y; + x1 = ppt->x; + y1 = ppt->y; + dashOffset = pGC->dashOffset; + totalDash = 0; + if (pGC->lineStyle != LineSolid) + totalDash = pPriv->dashLength; + while (--npt) + { + ++ppt; + x2 = ppt->x; + y2 = ppt->y; + if (mode == CoordModePrevious) + { + x2 += x1; + y2 += y1; + } + fbSegment (pDrawable, pGC, x1 + x, y1 + y, + x2 + x, y2 + y, + npt == 1 && pGC->capStyle != CapNotLast, + &dashOffset); + x1 = x2; + y1 = y2; + } +} + +void +fbZeroSegment (DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pSegs) +{ + int dashOffset; + int x, y; + Bool drawLast = pGC->capStyle != CapNotLast; + + x = pDrawable->x; + y = pDrawable->y; + while (nseg--) + { + dashOffset = pGC->dashOffset; + fbSegment (pDrawable, pGC, + pSegs->x1 + x, pSegs->y1 + y, + pSegs->x2 + x, pSegs->y2 + y, + drawLast, + &dashOffset); + pSegs++; + } +} + +void +fbFixCoordModePrevious (int npt, + DDXPointPtr ppt) +{ + int x, y; + + x = ppt->x; + y = ppt->y; + npt--; + while (npt--) + { + ppt++; + x = (ppt->x += x); + y = (ppt->y += y); + } +} + +void +fbPolyLine (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ppt) +{ + void (*line) (DrawablePtr, GCPtr, int mode, int npt, DDXPointPtr ppt); + + if (pGC->lineWidth == 0) + { + line = fbZeroLine; +#ifndef FBNOPIXADDR + if (pGC->fillStyle == FillSolid && + pGC->lineStyle == LineSolid && + REGION_NUM_RECTS (fbGetCompositeClip(pGC)) == 1) + { + switch (pDrawable->bitsPerPixel) { + case 8: line = fbPolyline8; break; + case 16: line = fbPolyline16; break; +#ifdef FB_24BIT + case 24: line = fbPolyline24; break; +#endif + case 32: line = fbPolyline32; break; + } + } +#endif + } + else + { + if (pGC->lineStyle != LineSolid) + line = miWideDash; + else + line = miWideLine; + } + (*line) (pDrawable, pGC, mode, npt, ppt); +} + +void +fbPolySegment (DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pseg) +{ + void (*seg) (DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pseg); + + if (pGC->lineWidth == 0) + { + seg = fbZeroSegment; +#ifndef FBNOPIXADDR + if (pGC->fillStyle == FillSolid && + pGC->lineStyle == LineSolid && + REGION_NUM_RECTS (fbGetCompositeClip(pGC)) == 1) + { + switch (pDrawable->bitsPerPixel) { + case 8: seg = fbPolySegment8; break; + case 16: seg = fbPolySegment16; break; +#ifdef FB_24BIT + case 24: seg = fbPolySegment24; break; +#endif + case 32: seg = fbPolySegment32; break; + } + } +#endif + } + else + { + seg = miPolySegment; + } + (*seg) (pDrawable, pGC, nseg, pseg); +} diff --git a/fb/fboverlay.c b/fb/fboverlay.c new file mode 100644 index 000000000..761cf0949 --- /dev/null +++ b/fb/fboverlay.c @@ -0,0 +1,449 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fboverlay.c,v 1.5 2002/09/16 18:05:34 eich Exp $ + * + * Copyright © 2000 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. + */ + +#include "fb.h" +#include "fboverlay.h" + +int fbOverlayGeneration; +int fbOverlayScreenPrivateIndex = -1; + +/* + * Replace this if you want something supporting + * multiple overlays with the same depth + */ +Bool +fbOverlayCreateWindow(WindowPtr pWin) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); + int i; + PixmapPtr pPixmap; + + if (pWin->drawable.class != InputOutput) + return TRUE; + +#ifdef FB_SCREEN_PRIVATE + if (pWin->drawable.bitsPerPixel == 32) + pWin->drawable.bitsPerPixel = fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp; +#endif + + for (i = 0; i < pScrPriv->nlayers; i++) + { + pPixmap = pScrPriv->layer[i].u.run.pixmap; + if (pWin->drawable.depth == pPixmap->drawable.depth) + { + pWin->devPrivates[fbWinPrivateIndex].ptr = (pointer) pPixmap; + /* + * Make sure layer keys are written correctly by + * having non-root layers set to full while the + * root layer is set to empty. This will cause + * all of the layers to get painted when the root + * is mapped + */ + if (!pWin->parent) + { + REGION_EMPTY (pWin->drawable.pScreen, + &pScrPriv->layer[i].u.run.region); + } + return TRUE; + } + } + return FALSE; +} + +Bool +fbOverlayCloseScreen (int iScreen, ScreenPtr pScreen) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + int i; + + for (i = 0; i < pScrPriv->nlayers; i++) + { + (*pScreen->DestroyPixmap)(pScrPriv->layer[i].u.run.pixmap); + REGION_UNINIT (pScreen, &pScrPriv->layer[i].u.run.region); + } + return TRUE; +} + +/* + * Return layer containing this window + */ +int +fbOverlayWindowLayer(WindowPtr pWin) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); + int i; + + for (i = 0; i < pScrPriv->nlayers; i++) + if (pWin->devPrivates[fbWinPrivateIndex].ptr == + (pointer) pScrPriv->layer[i].u.run.pixmap) + return i; + return 0; +} + +Bool +fbOverlayCreateScreenResources(ScreenPtr pScreen) +{ + int i; + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + PixmapPtr pPixmap; + pointer pbits; + int width; + int depth; + BoxRec box; + + if (!miCreateScreenResources(pScreen)) + return FALSE; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + for (i = 0; i < pScrPriv->nlayers; i++) + { + pbits = pScrPriv->layer[i].u.init.pbits; + width = pScrPriv->layer[i].u.init.width; + depth = pScrPriv->layer[i].u.init.depth; + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth); + if (!pPixmap) + return FALSE; + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width, + pScreen->height, depth, + BitsPerPixel(depth), + PixmapBytePad(width, depth), + pbits)) + return FALSE; + pScrPriv->layer[i].u.run.pixmap = pPixmap; + REGION_INIT(pScreen, &pScrPriv->layer[i].u.run.region, &box, 0); + } + pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap; + return TRUE; +} + +void +fbOverlayPaintKey (DrawablePtr pDrawable, + RegionPtr pRegion, + CARD32 pixel, + int layer) +{ + fbFillRegionSolid (pDrawable, pRegion, 0, + fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); +} + +/* + * Track visible region for each layer + */ +void +fbOverlayUpdateLayerRegion (ScreenPtr pScreen, + int layer, + RegionPtr prgn) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + int i; + RegionRec rgnNew; + + if (!prgn || !REGION_NOTEMPTY(pScreen, prgn)) + return; + for (i = 0; i < pScrPriv->nlayers; i++) + { + if (i == layer) + { + /* add new piece to this fb */ + REGION_UNION (pScreen, + &pScrPriv->layer[i].u.run.region, + &pScrPriv->layer[i].u.run.region, + prgn); + } + else if (REGION_NOTEMPTY (pScreen, + &pScrPriv->layer[i].u.run.region)) + { + /* paint new piece with chroma key */ + REGION_INIT (pScreen, &rgnNew, NullBox, 0); + REGION_INTERSECT (pScreen, + &rgnNew, + prgn, + &pScrPriv->layer[i].u.run.region); + (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable, + &rgnNew, + pScrPriv->layer[i].key, + i); + REGION_UNINIT(pScreen, &rgnNew); + /* remove piece from other fbs */ + REGION_SUBTRACT (pScreen, + &pScrPriv->layer[i].u.run.region, + &pScrPriv->layer[i].u.run.region, + prgn); + } + } +} + +/* + * Copy only areas in each layer containing real bits + */ +void +fbOverlayCopyWindow(WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen); + RegionRec rgnDst; + int dx, dy; + WindowPtr pwinRoot; + int i; + RegionRec layerRgn[FB_OVERLAY_MAX]; + PixmapPtr pPixmap; + + pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + + /* + * Clip to existing bits + */ + REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); + REGION_INIT (pScreen, &rgnDst, NullBox, 0); + REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + REGION_TRANSLATE(pScreen, &rgnDst, dx, dy); + /* + * Compute the portion of each fb affected by this copy + */ + for (i = 0; i < pScrPriv->nlayers; i++) + { + REGION_INIT (pScreen, &layerRgn[i], NullBox, 0); + REGION_INTERSECT(pScreen, &layerRgn[i], &rgnDst, + &pScrPriv->layer[i].u.run.region); + if (REGION_NOTEMPTY (pScreen, &layerRgn[i])) + { + REGION_TRANSLATE(pScreen, &layerRgn[i], -dx, -dy); + pPixmap = pScrPriv->layer[i].u.run.pixmap; + fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable, + 0, + &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0, + (void *)(long) i); + } + } + /* + * Update regions + */ + for (i = 0; i < pScrPriv->nlayers; i++) + { + if (REGION_NOTEMPTY (pScreen, &layerRgn[i])) + fbOverlayUpdateLayerRegion (pScreen, i, &layerRgn[i]); + + REGION_UNINIT(pScreen, &layerRgn[i]); + } + REGION_UNINIT(pScreen, &rgnDst); +} + +void +fbOverlayWindowExposures (WindowPtr pWin, + RegionPtr prgn, + RegionPtr other_exposed) +{ + fbOverlayUpdateLayerRegion (pWin->drawable.pScreen, + fbOverlayWindowLayer (pWin), + prgn); + miWindowExposures(pWin, prgn, other_exposed); +} + +void +fbOverlayPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) +{ + if (what == PW_BORDER) + fbOverlayUpdateLayerRegion (pWin->drawable.pScreen, + fbOverlayWindowLayer (pWin), + pRegion); + fbPaintWindow (pWin, pRegion, what); +} + +Bool +fbOverlaySetupScreen(ScreenPtr pScreen, + pointer pbits1, + pointer pbits2, + int xsize, + int ysize, + int dpix, + int dpiy, + int width1, + int width2, + int bpp1, + int bpp2) +{ + return fbSetupScreen (pScreen, + pbits1, + xsize, + ysize, + dpix, + dpiy, + width1, + bpp1); +} + +static Bool +fb24_32OverlayCreateScreenResources(ScreenPtr pScreen) +{ + FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen); + int pitch; + Bool retval; + int i; + + if((retval = fbOverlayCreateScreenResources(pScreen))) { + for (i = 0; i < pScrPriv->nlayers; i++) + { + /* fix the screen pixmap */ + PixmapPtr pPix = (PixmapPtr) pScrPriv->layer[i].u.run.pixmap; + if (pPix->drawable.bitsPerPixel == 32) { + pPix->drawable.bitsPerPixel = 24; + pitch = BitmapBytePad(pPix->drawable.width * 24); + pPix->devKind = pitch; + } + } + } + + return retval; +} + +Bool +fbOverlayFinishScreenInit(ScreenPtr pScreen, + pointer pbits1, + pointer pbits2, + int xsize, + int ysize, + int dpix, + int dpiy, + int width1, + int width2, + int bpp1, + int bpp2, + int depth1, + int depth2) +{ + VisualPtr visuals; + DepthPtr depths; + int nvisuals; + int ndepths; + int bpp = 0, imagebpp = 32; + VisualID defaultVisual; + FbOverlayScrPrivPtr pScrPriv; + + if (fbOverlayGeneration != serverGeneration) + { + fbOverlayScreenPrivateIndex = AllocateScreenPrivateIndex (); + fbOverlayGeneration = serverGeneration; + } + + pScrPriv = xalloc (sizeof (FbOverlayScrPrivRec)); + if (!pScrPriv) + return FALSE; + +#ifdef FB_24_32BIT + if (bpp1 == 32 || bpp2 == 32) + bpp = 32; + else if (bpp1 == 24 || bpp2 == 24) + bpp = 24; + + if (bpp == 24) + { + int f; + + imagebpp = 32; + /* + * Check to see if we're advertising a 24bpp image format, + * in which case windows will use it in preference to a 32 bit + * format. + */ + for (f = 0; f < screenInfo.numPixmapFormats; f++) + { + if (screenInfo.formats[f].bitsPerPixel == 24) + { + imagebpp = 24; + break; + } + } + } +#endif +#ifdef FB_SCREEN_PRIVATE + if (imagebpp == 32) + { + fbGetScreenPrivate(pScreen)->win32bpp = bpp; + fbGetScreenPrivate(pScreen)->pix32bpp = bpp; + } + else + { + fbGetScreenPrivate(pScreen)->win32bpp = 32; + fbGetScreenPrivate(pScreen)->pix32bpp = 32; + } +#endif + + if (!fbInitVisuals (&visuals, &depths, &nvisuals, &ndepths, &depth1, + &defaultVisual, ((unsigned long)1<<(bpp1-1)) | + ((unsigned long)1<<(bpp2-1)), 8)) + return FALSE; + if (! miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0, + depth1, ndepths, depths, + defaultVisual, nvisuals, visuals +#ifdef FB_OLD_SCREEN + , (miBSFuncPtr) 0 +#endif + )) + return FALSE; + /* MI thinks there's no frame buffer */ +#ifdef MITSHM + ShmRegisterFbFuncs(pScreen); +#endif + pScreen->minInstalledCmaps = 1; + pScreen->maxInstalledCmaps = 2; + + pScrPriv->nlayers = 2; + pScrPriv->PaintKey = fbOverlayPaintKey; + pScrPriv->CopyWindow = fbCopyWindowProc; + pScrPriv->layer[0].u.init.pbits = pbits1; + pScrPriv->layer[0].u.init.width = width1; + pScrPriv->layer[0].u.init.depth = depth1; + + pScrPriv->layer[1].u.init.pbits = pbits2; + pScrPriv->layer[1].u.init.width = width2; + pScrPriv->layer[1].u.init.depth = depth2; + + pScreen->devPrivates[fbOverlayScreenPrivateIndex].ptr = (pointer) pScrPriv; + + /* overwrite miCloseScreen with our own */ + pScreen->CloseScreen = fbOverlayCloseScreen; + pScreen->CreateScreenResources = fbOverlayCreateScreenResources; + pScreen->CreateWindow = fbOverlayCreateWindow; + pScreen->WindowExposures = fbOverlayWindowExposures; + pScreen->CopyWindow = fbOverlayCopyWindow; + pScreen->PaintWindowBorder = fbOverlayPaintWindow; +#ifdef FB_24_32BIT + if (bpp == 24 && imagebpp == 32) + { + pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader; + pScreen->CreateScreenResources = fb24_32OverlayCreateScreenResources; + } +#endif + + return TRUE; +} diff --git a/fb/fboverlay.h b/fb/fboverlay.h new file mode 100644 index 000000000..3dca8a3a4 --- /dev/null +++ b/fb/fboverlay.h @@ -0,0 +1,128 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fboverlay.h,v 1.5 2002/09/19 13:22:00 tsi Exp $ + * + * Copyright © 2000 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. + */ + +#ifndef _FBOVERLAY_H_ +#define _FBOVERLAY_H_ + +extern int fbOverlayGeneration; +extern int fbOverlayScreenPrivateIndex; + +#ifndef FB_OVERLAY_MAX +#define FB_OVERLAY_MAX 2 +#endif + +typedef void (*fbOverlayPaintKeyProc) (DrawablePtr, RegionPtr, CARD32, int); + +typedef struct _fbOverlayLayer { + union { + struct { + pointer pbits; + int width; + int depth; + } init; + struct { + PixmapPtr pixmap; + RegionRec region; + } run; + } u; + CARD32 key; /* special pixel value */ +} FbOverlayLayer; + +typedef struct _fbOverlayScrPriv { + int nlayers; + fbOverlayPaintKeyProc PaintKey; + fbCopyProc CopyWindow; + FbOverlayLayer layer[FB_OVERLAY_MAX]; +} FbOverlayScrPrivRec, *FbOverlayScrPrivPtr; + +#define fbOverlayGetScrPriv(s) \ + ((fbOverlayScreenPrivateIndex != -1) ? \ + (s)->devPrivates[fbOverlayScreenPrivateIndex].ptr : NULL) +Bool +fbOverlayCreateWindow(WindowPtr pWin); + +Bool +fbOverlayCloseScreen (int iScreen, ScreenPtr pScreen); + +int +fbOverlayWindowLayer(WindowPtr pWin); + +Bool +fbOverlayCreateScreenResources(ScreenPtr pScreen); + +void +fbOverlayPaintKey (DrawablePtr pDrawable, + RegionPtr pRegion, + CARD32 pixel, + int layer); +void +fbOverlayUpdateLayerRegion (ScreenPtr pScreen, + int layer, + RegionPtr prgn); + + +void +fbOverlayCopyWindow(WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc); + +void +fbOverlayWindowExposures (WindowPtr pWin, + RegionPtr prgn, + RegionPtr other_exposed); + +void +fbOverlayPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); + + +Bool +fbOverlaySetupScreen(ScreenPtr pScreen, + pointer pbits1, + pointer pbits2, + int xsize, + int ysize, + int dpix, + int dpiy, + int width1, + int width2, + int bpp1, + int bpp2); + +Bool +fbOverlayFinishScreenInit(ScreenPtr pScreen, + pointer pbits1, + pointer pbits2, + int xsize, + int ysize, + int dpix, + int dpiy, + int width1, + int width2, + int bpp1, + int bpp2, + int depth1, + int depth2); + +#endif /* _FBOVERLAY_H_ */ diff --git a/fb/fbpict.c b/fb/fbpict.c new file mode 100644 index 000000000..894d5cd62 --- /dev/null +++ b/fb/fbpict.c @@ -0,0 +1,1167 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fbpict.c,v 1.16 2002/12/14 01:46:02 dawes Exp $ + * + * Copyright © 2000 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. + */ + +#include "fb.h" + +#ifdef RENDER + +#include "picturestr.h" +#include "mipict.h" +#include "fbpict.h" + +#define cvt8888to0565(s) ((((s) >> 3) & 0x001f) | \ + (((s) >> 5) & 0x07e0) | \ + (((s) >> 8) & 0xf800)) +#define cvt0565to8888(s) (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \ + ((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \ + ((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000))) + +#if IMAGE_BYTE_ORDER == MSBFirst +#define Fetch24(a) ((unsigned long) (a) & 1 ? \ + ((*(a) << 16) | *((CARD16 *) ((a)+1))) : \ + ((*((CARD16 *) (a)) << 8) | *((a)+2))) +#define Store24(a,v) ((unsigned long) (a) & 1 ? \ + ((*(a) = (CARD8) ((v) >> 16)), \ + (*((CARD16 *) ((a)+1)) = (CARD16) (v))) : \ + ((*((CARD16 *) (a)) = (CARD16) ((v) >> 8)), \ + (*((a)+2) = (CARD8) (v)))) +#else +#define Fetch24(a) ((unsigned long) (a) & 1 ? \ + ((*(a)) | (*((CARD16 *) ((a)+1)) << 8)) : \ + ((*((CARD16 *) (a))) | (*((a)+2) << 16))) +#define Store24(a,v) ((unsigned long) (a) & 1 ? \ + ((*(a) = (CARD8) (v)), \ + (*((CARD16 *) ((a)+1)) = (CARD16) ((v) >> 8))) : \ + ((*((CARD16 *) (a)) = (CARD16) (v)),\ + (*((a)+2) = (CARD8) ((v) >> 16)))) +#endif + +CARD32 +fbOver (CARD32 x, CARD32 y) +{ + CARD16 a = ~x >> 24; + CARD16 t; + CARD32 m,n,o,p; + + m = FbOverU(x,y,0,a,t); + n = FbOverU(x,y,8,a,t); + o = FbOverU(x,y,16,a,t); + p = FbOverU(x,y,24,a,t); + return m|n|o|p; +} + +CARD32 +fbOver24 (CARD32 x, CARD32 y) +{ + CARD16 a = ~x >> 24; + CARD16 t; + CARD32 m,n,o; + + m = FbOverU(x,y,0,a,t); + n = FbOverU(x,y,8,a,t); + o = FbOverU(x,y,16,a,t); + return m|n|o; +} + +CARD32 +fbIn (CARD32 x, CARD8 y) +{ + CARD16 a = y; + CARD16 t; + CARD32 m,n,o,p; + + m = FbInU(x,0,a,t); + n = FbInU(x,8,a,t); + o = FbInU(x,16,a,t); + p = FbInU(x,24,a,t); + return m|n|o|p; +} + +#define fbComposeGetSolid(pict, bits) { \ + FbBits *__bits__; \ + FbStride __stride__; \ + int __bpp__; \ + int __xoff__,__yoff__; \ +\ + fbGetDrawable((pict)->pDrawable,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \ + switch (__bpp__) { \ + case 32: \ + (bits) = *(CARD32 *) __bits__; \ + break; \ + case 24: \ + (bits) = Fetch24 ((CARD8 *) __bits__); \ + break; \ + case 16: \ + (bits) = *(CARD16 *) __bits__; \ + (bits) = cvt0565to8888(bits); \ + break; \ + default: \ + return; \ + } \ + /* manage missing src alpha */ \ + if ((pict)->pFormat->direct.alphaMask == 0) \ + (bits) |= 0xff000000; \ +} + +#define fbComposeGetStart(pict,x,y,type,stride,line,mul) {\ + FbBits *__bits__; \ + FbStride __stride__; \ + int __bpp__; \ + int __xoff__,__yoff__; \ +\ + fbGetDrawable((pict)->pDrawable,__bits__,__stride__,__bpp__,__xoff__,__yoff__); \ + (stride) = __stride__ * sizeof (FbBits) / sizeof (type); \ + (line) = ((type *) __bits__) + (stride) * ((y) - __yoff__) + (mul) * ((x) - __xoff__); \ +} + +/* + * Naming convention: + * + * opSRCxMASKxDST + */ + +void +fbCompositeSolidMask_nx8x8888 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD32 src, srca; + CARD32 *dstLine, *dst, d, dstMask; + CARD8 *maskLine, *mask, m; + FbStride dstStride, maskStride; + CARD16 w; + + fbComposeGetSolid(pSrc, src); + + dstMask = FbFullMask (pDst->pDrawable->depth); + srca = src >> 24; + if (src == 0) + return; + + fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); + fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) + { + m = *mask++; + if (m == 0xff) + { + if (srca == 0xff) + *dst = src & dstMask; + else + *dst = fbOver (src, *dst) & dstMask; + } + else if (m) + { + d = fbIn (src, m); + *dst = fbOver (d, *dst) & dstMask; + } + dst++; + } + } +} + +void +fbCompositeSolidMask_nx8888x8888C (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD32 src, srca; + CARD32 *dstLine, *dst, d, dstMask; + CARD32 *maskLine, *mask, ma; + FbStride dstStride, maskStride; + CARD16 w; + CARD32 m, n, o, p; + + fbComposeGetSolid(pSrc, src); + + dstMask = FbFullMask (pDst->pDrawable->depth); + srca = src >> 24; + if (src == 0) + return; + + fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); + fbComposeGetStart (pMask, xMask, yMask, CARD32, maskStride, maskLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) + { + ma = *mask++; + if (ma == 0xffffffff) + { + if (srca == 0xff) + *dst = src & dstMask; + else + *dst = fbOver (src, *dst) & dstMask; + } + else if (ma) + { + d = *dst; +#define FbInOverC(src,srca,msk,dst,i,result) { \ + CARD16 __a = FbGet8(msk,i); \ + CARD32 __t, __ta; \ + CARD32 __i; \ + __t = FbIntMult (FbGet8(src,i), __a,__i); \ + __ta = (CARD8) ~FbIntMult (srca, __a,__i); \ + __t = __t + FbIntMult(FbGet8(dst,i),__ta,__i); \ + __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \ + result = __t << (i); \ +} + FbInOverC (src, srca, ma, d, 0, m); + FbInOverC (src, srca, ma, d, 8, n); + FbInOverC (src, srca, ma, d, 16, o); + FbInOverC (src, srca, ma, d, 24, p); + *dst = m|n|o|p; + } + dst++; + } + } +} + +void +fbCompositeSolidMask_nx8x0888 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD32 src, srca; + CARD8 *dstLine, *dst; + CARD32 d; + CARD8 *maskLine, *mask, m; + FbStride dstStride, maskStride; + CARD16 w; + + fbComposeGetSolid(pSrc, src); + + srca = src >> 24; + if (src == 0) + return; + + fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 3); + fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) + { + m = *mask++; + if (m == 0xff) + { + if (srca == 0xff) + d = src; + else + { + d = Fetch24(dst); + d = fbOver24 (src, d); + } + Store24(dst,d); + } + else if (m) + { + d = fbOver24 (fbIn(src,m), Fetch24(dst)); + Store24(dst,d); + } + dst += 3; + } + } +} + +void +fbCompositeSolidMask_nx8x0565 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD32 src, srca; + CARD16 *dstLine, *dst; + CARD32 d; + CARD8 *maskLine, *mask, m; + FbStride dstStride, maskStride; + CARD16 w; + + fbComposeGetSolid(pSrc, src); + + srca = src >> 24; + if (src == 0) + return; + + fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); + fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) + { + m = *mask++; + if (m == 0xff) + { + if (srca == 0xff) + d = src; + else + { + d = *dst; + d = fbOver24 (src, cvt0565to8888(d)); + } + *dst = cvt8888to0565(d); + } + else if (m) + { + d = *dst; + d = fbOver24 (fbIn(src,m), cvt0565to8888(d)); + *dst = cvt8888to0565(d); + } + dst++; + } + } +} + +void +fbCompositeSolidMask_nx8888x0565C (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD32 src, srca; + CARD16 src16; + CARD16 *dstLine, *dst; + CARD32 d; + CARD32 *maskLine, *mask, ma; + FbStride dstStride, maskStride; + CARD16 w; + CARD32 m, n, o; + + fbComposeGetSolid(pSrc, src); + + srca = src >> 24; + if (src == 0) + return; + + src16 = cvt8888to0565(src); + + fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); + fbComposeGetStart (pMask, xMask, yMask, CARD32, maskStride, maskLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + mask = maskLine; + maskLine += maskStride; + w = width; + + while (w--) + { + ma = *mask++; + if (ma == 0xffffffff) + { + if (srca == 0xff) + { + *dst = src16; + } + else + { + d = *dst; + d = fbOver24 (src, cvt0565to8888(d)); + *dst = cvt8888to0565(d); + } + } + else if (ma) + { + d = *dst; + d = cvt0565to8888(d); + FbInOverC (src, srca, ma, d, 0, m); + FbInOverC (src, srca, ma, d, 8, n); + FbInOverC (src, srca, ma, d, 16, o); + d = m|n|o; + *dst = cvt8888to0565(d); + } + dst++; + } + } +} + +void +fbCompositeSrc_8888x8888 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD32 *dstLine, *dst, dstMask; + CARD32 *srcLine, *src, s; + FbStride dstStride, srcStride; + CARD8 a; + CARD16 w; + + fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); + fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); + + dstMask = FbFullMask (pDst->pDrawable->depth); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) + { + s = *src++; + a = s >> 24; + if (a == 0xff) + *dst = s & dstMask; + else if (a) + *dst = fbOver (s, *dst) & dstMask; + dst++; + } + } +} + +void +fbCompositeSrc_8888x0888 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD8 *dstLine, *dst; + CARD32 d; + CARD32 *srcLine, *src, s; + CARD8 a; + FbStride dstStride, srcStride; + CARD16 w; + + fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 3); + fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) + { + s = *src++; + a = s >> 24; + if (a) + { + if (a == 0xff) + d = s; + else + d = fbOver24 (s, Fetch24(dst)); + Store24(dst,d); + } + dst += 3; + } + } +} + +void +fbCompositeSrc_8888x0565 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD16 *dstLine, *dst; + CARD32 d; + CARD32 *srcLine, *src, s; + CARD8 a; + FbStride dstStride, srcStride; + CARD16 w; + + fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); + fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) + { + s = *src++; + a = s >> 24; + if (a) + { + if (a == 0xff) + d = s; + else + { + d = *dst; + d = fbOver24 (s, cvt0565to8888(d)); + } + *dst = cvt8888to0565(d); + } + dst++; + } + } +} + +void +fbCompositeSrc_0565x0565 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD16 *dstLine, *dst; + CARD16 *srcLine, *src; + FbStride dstStride, srcStride; + CARD16 w; + + fbComposeGetStart (pSrc, xSrc, ySrc, CARD16, srcStride, srcLine, 1); + + fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) + *dst++ = *src++; + } +} + +void +fbCompositeSrcAdd_8000x8000 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD8 *dstLine, *dst; + CARD8 *srcLine, *src; + FbStride dstStride, srcStride; + CARD16 w; + CARD8 s, d; + CARD16 t; + + fbComposeGetStart (pSrc, xSrc, ySrc, CARD8, srcStride, srcLine, 1); + fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) + { + s = *src++; + if (s) + { + if (s != 0xff) + { + d = *dst; + t = d + s; + s = t | (0 - (t >> 8)); + } + *dst = s; + } + dst++; + } + } +} + +void +fbCompositeSrcAdd_8888x8888 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD32 *dstLine, *dst; + CARD32 *srcLine, *src; + FbStride dstStride, srcStride; + CARD16 w; + CARD32 s, d; + CARD16 t; + CARD32 m,n,o,p; + + fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); + fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) + { + s = *src++; + if (s) + { + if (s != 0xffffffff) + { + d = *dst; + if (d) + { + m = FbAdd(s,d,0,t); + n = FbAdd(s,d,8,t); + o = FbAdd(s,d,16,t); + p = FbAdd(s,d,24,t); + s = m|n|o|p; + } + } + *dst = s; + } + dst++; + } + } +} + +void +fbCompositeSrcAdd_1000x1000 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + FbBits *dstBits, *srcBits; + FbStride dstStride, srcStride; + int dstBpp, srcBpp; + int dstXoff, dstYoff; + int srcXoff, srcYoff; + + fbGetDrawable(pSrc->pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); + + fbGetDrawable(pDst->pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + + fbBlt (srcBits + srcStride * (ySrc + srcYoff), + srcStride, + xSrc + srcXoff, + + dstBits + dstStride * (yDst + dstYoff), + dstStride, + xDst + dstXoff, + + width, + height, + + GXor, + FB_ALLONES, + srcBpp, + + FALSE, + FALSE); +} + +void +fbCompositeSolidMask_nx1xn (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + FbBits *dstBits; + FbStip *maskBits; + FbStride dstStride, maskStride; + int dstBpp, maskBpp; + int dstXoff, dstYoff; + int maskXoff, maskYoff; + FbBits src; + + fbComposeGetSolid(pSrc, src); + + if ((src & 0xff000000) != 0xff000000) + { + fbCompositeGeneral (op, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, + width, height); + return; + } + fbGetStipDrawable (pMask->pDrawable, maskBits, maskStride, maskBpp, maskXoff, maskYoff); + fbGetDrawable (pDst->pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); + + switch (dstBpp) { + case 32: + break; + case 24: + break; + case 16: + src = cvt8888to0565(src); + break; + } + + src = fbReplicatePixel (src, dstBpp); + + fbBltOne (maskBits + maskStride * (yMask + maskYoff), + maskStride, + xMask + maskXoff, + + dstBits + dstStride * (yDst + dstYoff), + dstStride, + (xDst + dstXoff) * dstBpp, + dstBpp, + + width * dstBpp, + height, + + 0x0, + src, + FB_ALLONES, + 0x0); +} + +# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b)) + +void +fbComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + RegionRec region; + int n; + BoxPtr pbox; + CompositeFunc func; + Bool srcRepeat = pSrc->repeat; + Bool maskRepeat = FALSE; + Bool srcAlphaMap = pSrc->alphaMap != 0; + Bool maskAlphaMap = FALSE; + Bool dstAlphaMap = pDst->alphaMap != 0; + int x_msk, y_msk, x_src, y_src, x_dst, y_dst; + int w, h, w_this, h_this; + + xDst += pDst->pDrawable->x; + yDst += pDst->pDrawable->y; + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + if (pMask) + { + xMask += pMask->pDrawable->x; + yMask += pMask->pDrawable->y; + maskRepeat = pMask->repeat; + maskAlphaMap = pMask->alphaMap != 0; + } + + if (!miComputeCompositeRegion (®ion, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height)) + return; + + func = fbCompositeGeneral; + if (!pSrc->transform && !(pMask && pMask->transform)) + if (!maskAlphaMap && !srcAlphaMap && !dstAlphaMap) + switch (op) { + case PictOpOver: + if (pMask) + { + if (srcRepeat && + pSrc->pDrawable->width == 1 && + pSrc->pDrawable->height == 1) + { + srcRepeat = FALSE; + if (PICT_FORMAT_COLOR(pSrc->format)) { + switch (pMask->format) { + case PICT_a8: + switch (pDst->format) { + case PICT_r5g6b5: + case PICT_b5g6r5: + func = fbCompositeSolidMask_nx8x0565; + break; + case PICT_r8g8b8: + case PICT_b8g8r8: + func = fbCompositeSolidMask_nx8x0888; + break; + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + func = fbCompositeSolidMask_nx8x8888; + break; + } + break; + case PICT_a8r8g8b8: + if (pMask->componentAlpha) { + switch (pDst->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + func = fbCompositeSolidMask_nx8888x8888C; + break; + case PICT_r5g6b5: + func = fbCompositeSolidMask_nx8888x0565C; + break; + } + } + break; + case PICT_a8b8g8r8: + if (pMask->componentAlpha) { + switch (pDst->format) { + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + func = fbCompositeSolidMask_nx8888x8888C; + break; + case PICT_b5g6r5: + func = fbCompositeSolidMask_nx8888x0565C; + break; + } + } + break; + case PICT_a1: + switch (pDst->format) { + case PICT_r5g6b5: + case PICT_b5g6r5: + case PICT_r8g8b8: + case PICT_b8g8r8: + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + func = fbCompositeSolidMask_nx1xn; + break; + } + } + } + } + } + else + { + switch (pSrc->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + switch (pDst->format) { + case PICT_a8r8g8b8: + case PICT_x8r8g8b8: + func = fbCompositeSrc_8888x8888; + break; + case PICT_r8g8b8: + func = fbCompositeSrc_8888x0888; + break; + case PICT_r5g6b5: + func = fbCompositeSrc_8888x0565; + break; + } + break; + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + switch (pDst->format) { + case PICT_a8b8g8r8: + case PICT_x8b8g8r8: + func = fbCompositeSrc_8888x8888; + break; + case PICT_b8g8r8: + func = fbCompositeSrc_8888x0888; + break; + case PICT_b5g6r5: + func = fbCompositeSrc_8888x0565; + break; + } + break; + case PICT_r5g6b5: + switch (pDst->format) { + case PICT_r5g6b5: + func = fbCompositeSrc_0565x0565; + break; + } + break; + case PICT_b5g6r5: + switch (pDst->format) { + case PICT_b5g6r5: + func = fbCompositeSrc_0565x0565; + break; + } + break; + } + } + break; + case PictOpAdd: + if (pMask == 0) + { + switch (pSrc->format) { + case PICT_a8r8g8b8: + switch (pDst->format) { + case PICT_a8r8g8b8: + func = fbCompositeSrcAdd_8888x8888; + break; + } + break; + case PICT_a8b8g8r8: + switch (pDst->format) { + case PICT_a8b8g8r8: + func = fbCompositeSrcAdd_8888x8888; + break; + } + break; + case PICT_a8: + switch (pDst->format) { + case PICT_a8: + func = fbCompositeSrcAdd_8000x8000; + break; + } + break; + case PICT_a1: + switch (pDst->format) { + case PICT_a1: + func = fbCompositeSrcAdd_1000x1000; + break; + } + break; + } + } + break; + } + n = REGION_NUM_RECTS (®ion); + pbox = REGION_RECTS (®ion); + while (n--) + { + h = pbox->y2 - pbox->y1; + y_src = pbox->y1 - yDst + ySrc; + y_msk = pbox->y1 - yDst + yMask; + y_dst = pbox->y1; + while (h) + { + h_this = h; + w = pbox->x2 - pbox->x1; + x_src = pbox->x1 - xDst + xSrc; + x_msk = pbox->x1 - xDst + xMask; + x_dst = pbox->x1; + if (maskRepeat) + { + y_msk = mod (y_msk, pMask->pDrawable->height); + if (h_this > pMask->pDrawable->height - y_msk) + h_this = pMask->pDrawable->height - y_msk; + } + if (srcRepeat) + { + y_src = mod (y_src, pSrc->pDrawable->height); + if (h_this > pSrc->pDrawable->height - y_src) + h_this = pSrc->pDrawable->height - y_src; + } + while (w) + { + w_this = w; + if (maskRepeat) + { + x_msk = mod (x_msk, pMask->pDrawable->width); + if (w_this > pMask->pDrawable->width - x_msk) + w_this = pMask->pDrawable->width - x_msk; + } + if (srcRepeat) + { + x_src = mod (x_src, pSrc->pDrawable->width); + if (w_this > pSrc->pDrawable->width - x_src) + w_this = pSrc->pDrawable->width - x_src; + } + (*func) (op, pSrc, pMask, pDst, + x_src, y_src, x_msk, y_msk, x_dst, y_dst, + w_this, h_this); + w -= w_this; + x_src += w_this; + x_msk += w_this; + x_dst += w_this; + } + h -= h_this; + y_src += h_this; + y_msk += h_this; + y_dst += h_this; + } + pbox++; + } + REGION_UNINIT (pDst->pDrawable->pScreen, ®ion); +} + +#endif /* RENDER */ + +Bool +fbPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) +{ + +#ifdef RENDER + + PictureScreenPtr ps; + + if (!miPictureInit (pScreen, formats, nformats)) + return FALSE; + ps = GetPictureScreen(pScreen); + ps->Composite = fbComposite; + ps->Glyphs = miGlyphs; + ps->CompositeRects = miCompositeRects; + ps->RasterizeTrapezoid = fbRasterizeTrapezoid; + +#endif /* RENDER */ + + return TRUE; +} diff --git a/fb/fbpict.h b/fb/fbpict.h new file mode 100644 index 000000000..fd911b078 --- /dev/null +++ b/fb/fbpict.h @@ -0,0 +1,976 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fbpict.h,v 1.11 2002/09/26 02:56:48 keithp Exp $ + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, 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 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. + */ + +#ifndef _FBPICT_H_ +#define _FBPICT_H_ + +#define FbIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) ) +#define FbIntDiv(a,b) (((CARD16) (a) * 255) / (b)) + +#define FbGet8(v,i) ((CARD16) (CARD8) ((v) >> i)) + +/* + * There are two ways of handling alpha -- either as a single unified value or + * a separate value for each component, hence each macro must have two + * versions. The unified alpha version has a 'U' at the end of the name, + * the component version has a 'C'. Similarly, functions which deal with + * this difference will have two versions using the same convention. + */ + +#define FbOverU(x,y,i,a,t) ((t) = FbIntMult(FbGet8(y,i),(a),(t)) + FbGet8(x,i),\ + (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) + +#define FbOverC(x,y,i,a,t) ((t) = FbIntMult(FbGet8(y,i),FbGet8(a,i),(t)) + FbGet8(x,i),\ + (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) + +#define FbInU(x,i,a,t) ((CARD32) FbIntMult(FbGet8(x,i),(a),(t)) << (i)) + +#define FbInC(x,i,a,t) ((CARD32) FbIntMult(FbGet8(x,i),FbGet8(a,i),(t)) << (i)) + +#define FbGen(x,y,i,ax,ay,t,u,v) ((t) = (FbIntMult(FbGet8(y,i),ay,(u)) + \ + FbIntMult(FbGet8(x,i),ax,(v))),\ + (CARD32) ((CARD8) ((t) | \ + (0 - ((t) >> 8)))) << (i)) + +#define FbAdd(x,y,i,t) ((t) = FbGet8(x,i) + FbGet8(y,i), \ + (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i)) + + +typedef void (*CompositeFunc) (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +typedef struct _FbCompositeOperand FbCompositeOperand; + +typedef CARD32 (*FbCompositeFetch)(FbCompositeOperand *op); +typedef void (*FbCompositeStore) (FbCompositeOperand *op, CARD32 value); + +typedef void (*FbCompositeStep) (FbCompositeOperand *op); +typedef void (*FbCompositeSet) (FbCompositeOperand *op, int x, int y); + +struct _FbCompositeOperand { + union { + struct { + FbBits *top_line; + int left_offset; + + int start_offset; + FbBits *line; + CARD32 offset; + FbStride stride; + int bpp; + } drawable; + struct { + int alpha_dx; + int alpha_dy; + } external; + struct { + int top_y; + int left_x; + int start_x; + int x; + int y; + PictTransformPtr transform; + int filter; + } transform; + } u; + FbCompositeFetch fetch; + FbCompositeFetch fetcha; + FbCompositeStore store; + FbCompositeStep over; + FbCompositeStep down; + FbCompositeSet set; + miIndexedPtr indexed; + RegionPtr clip; +}; + +typedef void (*FbCombineFunc) (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +/* + * indexed by op + */ +extern FbCombineFunc fbCombineFunc[]; + +typedef struct _FbAccessMap { + CARD32 format; + FbCompositeFetch fetch; + FbCompositeFetch fetcha; + FbCompositeStore store; +} FbAccessMap; + +/* + * search on format + */ +extern FbAccessMap fbAccessMap[]; + +/* fbcompose.c */ + +typedef struct _fbCompSrc { + CARD32 value; + CARD32 alpha; +} FbCompSrc; + +/* + * All compositing operators * + */ + +CARD32 +fbCombineMaskU (FbCompositeOperand *src, + FbCompositeOperand *msk); + +FbCompSrc +fbCombineMaskC (FbCompositeOperand *src, + FbCompositeOperand *msk); + +CARD32 +fbCombineMaskValueC (FbCompositeOperand *src, + FbCompositeOperand *msk); + +CARD32 +fbCombineMaskAlphaU (FbCompositeOperand *src, + FbCompositeOperand *msk); + +CARD32 +fbCombineMaskAlphaC (FbCompositeOperand *src, + FbCompositeOperand *msk); + + +#if 0 +CARD32 +FbCombineMask (FbCompositeOperand *src, + FbCompositeOperand *msk); +#endif + +void +fbCombineClear (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineSrcU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineSrcC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDst (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineOverU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineOverC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineOverReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineOverReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineInU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineInC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineInReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineInReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineOutU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineOutC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineOutReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineOutReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineAtopU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + + +void +fbCombineAtopC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineAtopReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineAtopReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineXorU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineXorC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + + +void +fbCombineAddU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineAddC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineSaturateU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineSaturateC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +CARD8 +fbCombineDisjointOutPart (CARD8 a, CARD8 b); + +CARD8 +fbCombineDisjointInPart (CARD8 a, CARD8 b); + +void +fbCombineDisjointGeneralU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine); + +void +fbCombineDisjointGeneralC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine); + +void +fbCombineDisjointOverU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointOverC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointOverReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointOverReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointInU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointInC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointInReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointInReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointOutU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointOutC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); +void +fbCombineDisjointOutReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointOutReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointAtopU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointAtopC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointAtopReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointAtopReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointXorU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineDisjointXorC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +CARD8 +fbCombineConjointOutPart (CARD8 a, CARD8 b); + +CARD8 +fbCombineConjointInPart (CARD8 a, CARD8 b); + + +void +fbCombineConjointGeneralU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine); + +void +fbCombineConjointGeneralC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst, + CARD8 combine); + +void +fbCombineConjointOverU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointOverC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); +void +fbCombineConjointOverReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointOverReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointInU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointInC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointInReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + + +void +fbCombineConjointInReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointOutU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointOutC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointOutReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointOutReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointAtopU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointAtopC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointAtopReverseU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); +void +fbCombineConjointAtopReverseC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointXorU (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +void +fbCombineConjointXorC (FbCompositeOperand *src, + FbCompositeOperand *msk, + FbCompositeOperand *dst); + +/* + * All fetch functions + */ + +CARD32 +fbFetch_a8r8g8b8 (FbCompositeOperand *op); + +CARD32 +fbFetch_x8r8g8b8 (FbCompositeOperand *op); + +CARD32 +fbFetch_a8b8g8r8 (FbCompositeOperand *op); + +CARD32 +fbFetch_x8b8g8r8 (FbCompositeOperand *op); + +CARD32 +fbFetch_r8g8b8 (FbCompositeOperand *op); + +CARD32 +fbFetch_b8g8r8 (FbCompositeOperand *op); + +CARD32 +fbFetch_r5g6b5 (FbCompositeOperand *op); + +CARD32 +fbFetch_b5g6r5 (FbCompositeOperand *op); + +CARD32 +fbFetch_a1r5g5b5 (FbCompositeOperand *op); + +CARD32 +fbFetch_x1r5g5b5 (FbCompositeOperand *op); + +CARD32 +fbFetch_a1b5g5r5 (FbCompositeOperand *op); + +CARD32 +fbFetch_x1b5g5r5 (FbCompositeOperand *op); + +CARD32 +fbFetch_a4r4g4b4 (FbCompositeOperand *op); + +CARD32 +fbFetch_x4r4g4b4 (FbCompositeOperand *op); + +CARD32 +fbFetch_a4b4g4r4 (FbCompositeOperand *op); + +CARD32 +fbFetch_x4b4g4r4 (FbCompositeOperand *op); + +CARD32 +fbFetch_a8 (FbCompositeOperand *op); + +CARD32 +fbFetcha_a8 (FbCompositeOperand *op); + +CARD32 +fbFetch_r3g3b2 (FbCompositeOperand *op); + +CARD32 +fbFetch_b2g3r3 (FbCompositeOperand *op); + +CARD32 +fbFetch_a2r2g2b2 (FbCompositeOperand *op); + +CARD32 +fbFetch_a2b2g2r2 (FbCompositeOperand *op); + +CARD32 +fbFetch_c8 (FbCompositeOperand *op); + +CARD32 +fbFetch_a4 (FbCompositeOperand *op); + +CARD32 +fbFetcha_a4 (FbCompositeOperand *op); + +CARD32 +fbFetch_r1g2b1 (FbCompositeOperand *op); + +CARD32 +fbFetch_b1g2r1 (FbCompositeOperand *op); + +CARD32 +fbFetch_a1r1g1b1 (FbCompositeOperand *op); + +CARD32 +fbFetch_a1b1g1r1 (FbCompositeOperand *op); + +CARD32 +fbFetch_c4 (FbCompositeOperand *op); + +CARD32 +fbFetch_a1 (FbCompositeOperand *op); + +CARD32 +fbFetcha_a1 (FbCompositeOperand *op); + +CARD32 +fbFetch_g1 (FbCompositeOperand *op); + +void +fbStore_a8r8g8b8 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_x8r8g8b8 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_a8b8g8r8 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_x8b8g8r8 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_r8g8b8 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_b8g8r8 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_r5g6b5 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_b5g6r5 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_a1r5g5b5 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_x1r5g5b5 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_a1b5g5r5 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_x1b5g5r5 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_a4r4g4b4 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_x4r4g4b4 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_a4b4g4r4 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_x4b4g4r4 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_a8 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_r3g3b2 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_b2g3r3 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_a2r2g2b2 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_c8 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_g8 (FbCompositeOperand *op, CARD32 value); + + +void +fbStore_a4 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_r1g2b1 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_b1g2r1 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_a1r1g1b1 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_a1b1g1r1 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_c4 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_g4 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_a1 (FbCompositeOperand *op, CARD32 value); + +void +fbStore_g1 (FbCompositeOperand *op, CARD32 value); + +CARD32 +fbFetch_external (FbCompositeOperand *op); + +CARD32 +fbFetch_transform (FbCompositeOperand *op); + +CARD32 +fbFetcha_transform (FbCompositeOperand *op); + +CARD32 +fbFetcha_external (FbCompositeOperand *op); + +void +fbStore_external (FbCompositeOperand *op, CARD32 value); + +Bool +fbBuildOneCompositeOperand (PicturePtr pPict, + FbCompositeOperand *op, + INT16 x, + INT16 y); + +Bool +fbBuildCompositeOperand (PicturePtr pPict, + FbCompositeOperand *op, + INT16 x, + INT16 y, + Bool transform, + Bool alpha); +void +fbCompositeGeneral (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + + +/* fbpict.c */ +CARD32 +fbOver (CARD32 x, CARD32 y); + +CARD32 +fbOver24 (CARD32 x, CARD32 y); + +CARD32 +fbIn (CARD32 x, CARD8 y); + +void +fbCompositeSolidMask_nx8x8888 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSolidMask_nx8x0888 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSolidMask_nx8888x8888C (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSolidMask_nx8x0565 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSolidMask_nx8888x0565C (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSrc_8888x8888 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSrc_8888x0888 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSrc_8888x0565 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSrc_0565x0565 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSrcAdd_8000x8000 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSrcAdd_8888x8888 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSrcAdd_1000x1000 (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbCompositeSolidMask_nx1xn (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +void +fbComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + +/* fbtrap.c */ +void +fbRasterizeTrapezoid (PicturePtr alpha, + xTrapezoid *trap, + int x_off, + int y_off); + +#endif /* _FBPICT_H_ */ diff --git a/fb/fbpixmap.c b/fb/fbpixmap.c new file mode 100644 index 000000000..757406c21 --- /dev/null +++ b/fb/fbpixmap.c @@ -0,0 +1,378 @@ +/* + * Id: fbpixmap.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbpixmap.c,v 1.11 2002/09/16 18:05:34 eich Exp $ */ + +#include "fb.h" +#ifdef IN_MODULE +#include "xf86_ansic.h" +#endif + +PixmapPtr +fbCreatePixmapBpp (ScreenPtr pScreen, int width, int height, int depth, int bpp) +{ + PixmapPtr pPixmap; + int datasize; + int paddedWidth; + int adjust; + int base; + + paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits); + datasize = height * paddedWidth; +#ifdef PIXPRIV + base = pScreen->totalPixmapSize; +#else + base = sizeof (PixmapRec); +#endif + adjust = 0; + if (base & 7) + adjust = 8 - (base & 7); + datasize += adjust; +#ifdef FB_DEBUG + datasize += 2 * paddedWidth; +#endif + pPixmap = AllocatePixmap(pScreen, datasize); + if (!pPixmap) + return NullPixmap; + pPixmap->drawable.type = DRAWABLE_PIXMAP; + pPixmap->drawable.class = 0; + pPixmap->drawable.pScreen = pScreen; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = bpp; + pPixmap->drawable.id = 0; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = paddedWidth; + pPixmap->refcnt = 1; + pPixmap->devPrivate.ptr = (pointer) ((char *)pPixmap + base + adjust); +#ifdef FB_DEBUG + pPixmap->devPrivate.ptr = (void *) ((char *) pPixmap->devPrivate.ptr + paddedWidth); + fbInitializeDrawable (&pPixmap->drawable); +#endif + + return pPixmap; +} + +PixmapPtr +fbCreatePixmap (ScreenPtr pScreen, int width, int height, int depth) +{ + int bpp; + bpp = BitsPerPixel (depth); +#ifdef FB_SCREEN_PRIVATE + if (bpp == 32 && depth <= 24) + bpp = fbGetScreenPrivate(pScreen)->pix32bpp; +#endif + return fbCreatePixmapBpp (pScreen, width, height, depth, bpp); +} + +Bool +fbDestroyPixmap (PixmapPtr pPixmap) +{ + if(--pPixmap->refcnt) + return TRUE; + xfree(pPixmap); + return TRUE; +} + +#define ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2) \ +if (((rx1) < (rx2)) && ((ry1) < (ry2)) && \ + (!((reg)->data->numRects && \ + ((r-1)->y1 == (ry1)) && \ + ((r-1)->y2 == (ry2)) && \ + ((r-1)->x1 <= (rx1)) && \ + ((r-1)->x2 >= (rx2))))) \ +{ \ + if ((reg)->data->numRects == (reg)->data->size) \ + { \ + miRectAlloc(reg, 1); \ + fr = REGION_BOXPTR(reg); \ + r = fr + (reg)->data->numRects; \ + } \ + r->x1 = (rx1); \ + r->y1 = (ry1); \ + r->x2 = (rx2); \ + r->y2 = (ry2); \ + (reg)->data->numRects++; \ + if(r->x1 < (reg)->extents.x1) \ + (reg)->extents.x1 = r->x1; \ + if(r->x2 > (reg)->extents.x2) \ + (reg)->extents.x2 = r->x2; \ + r++; \ +} + +/* Convert bitmap clip mask into clipping region. + * First, goes through each line and makes boxes by noting the transitions + * from 0 to 1 and 1 to 0. + * Then it coalesces the current line with the previous if they have boxes + * at the same X coordinates. + */ +RegionPtr +fbPixmapToRegion(PixmapPtr pPix) +{ + register RegionPtr pReg; + FbBits *pw, w; + register int ib; + int width, h, base, rx1 = 0, crects; + FbBits *pwLineEnd; + int irectPrevStart, irectLineStart; + register BoxPtr prectO, prectN; + BoxPtr FirstRect, rects, prectLineStart; + Bool fInBox, fSame; + register FbBits mask0 = FB_ALLONES & ~FbScrRight(FB_ALLONES, 1); + FbBits *pwLine; + int nWidth; + + pReg = REGION_CREATE(pPix->drawable.pScreen, NULL, 1); + if(!pReg) + return NullRegion; + FirstRect = REGION_BOXPTR(pReg); + rects = FirstRect; + + pwLine = (FbBits *) pPix->devPrivate.ptr; + nWidth = pPix->devKind >> (FB_SHIFT-3); + + width = pPix->drawable.width; + pReg->extents.x1 = width - 1; + pReg->extents.x2 = 0; + irectPrevStart = -1; + for(h = 0; h < pPix->drawable.height; h++) + { + pw = pwLine; + pwLine += nWidth; + irectLineStart = rects - FirstRect; + /* If the Screen left most bit of the word is set, we're starting in + * a box */ + if(*pw & mask0) + { + fInBox = TRUE; + rx1 = 0; + } + else + fInBox = FALSE; + /* Process all words which are fully in the pixmap */ + pwLineEnd = pw + (width >> FB_SHIFT); + for (base = 0; pw < pwLineEnd; base += FB_UNIT) + { + w = *pw++; + if (fInBox) + { + if (!~w) + continue; + } + else + { + if (!w) + continue; + } + for(ib = 0; ib < FB_UNIT; ib++) + { + /* If the Screen left most bit of the word is set, we're + * starting a box */ + if(w & mask0) + { + if(!fInBox) + { + rx1 = base + ib; + /* start new box */ + fInBox = TRUE; + } + } + else + { + if(fInBox) + { + /* end box */ + ADDRECT(pReg, rects, FirstRect, + rx1, h, base + ib, h + 1); + fInBox = FALSE; + } + } + /* Shift the word VISUALLY left one. */ + w = FbScrLeft(w, 1); + } + } + if(width & FB_MASK) + { + /* Process final partial word on line */ + w = *pw++; + for(ib = 0; ib < (width & FB_MASK); ib++) + { + /* If the Screen left most bit of the word is set, we're + * starting a box */ + if(w & mask0) + { + if(!fInBox) + { + rx1 = base + ib; + /* start new box */ + fInBox = TRUE; + } + } + else + { + if(fInBox) + { + /* end box */ + ADDRECT(pReg, rects, FirstRect, + rx1, h, base + ib, h + 1); + fInBox = FALSE; + } + } + /* Shift the word VISUALLY left one. */ + w = FbScrLeft(w, 1); + } + } + /* If scanline ended with last bit set, end the box */ + if(fInBox) + { + ADDRECT(pReg, rects, FirstRect, + rx1, h, base + (width & FB_MASK), h + 1); + } + /* if all rectangles on this line have the same x-coords as + * those on the previous line, then add 1 to all the previous y2s and + * throw away all the rectangles from this line + */ + fSame = FALSE; + if(irectPrevStart != -1) + { + crects = irectLineStart - irectPrevStart; + if(crects == ((rects - FirstRect) - irectLineStart)) + { + prectO = FirstRect + irectPrevStart; + prectN = prectLineStart = FirstRect + irectLineStart; + fSame = TRUE; + while(prectO < prectLineStart) + { + if((prectO->x1 != prectN->x1) || (prectO->x2 != prectN->x2)) + { + fSame = FALSE; + break; + } + prectO++; + prectN++; + } + if (fSame) + { + prectO = FirstRect + irectPrevStart; + while(prectO < prectLineStart) + { + prectO->y2 += 1; + prectO++; + } + rects -= crects; + pReg->data->numRects -= crects; + } + } + } + if(!fSame) + irectPrevStart = irectLineStart; + } + if (!pReg->data->numRects) + pReg->extents.x1 = pReg->extents.x2 = 0; + else + { + pReg->extents.y1 = REGION_BOXPTR(pReg)->y1; + pReg->extents.y2 = REGION_END(pReg)->y2; + if (pReg->data->numRects == 1) + { + xfree(pReg->data); + pReg->data = (RegDataPtr)NULL; + } + } +#ifdef DEBUG + if (!miValidRegion(pReg)) + FatalError("Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__); +#endif + return(pReg); +} + +#ifdef FB_DEBUG + +#ifndef WIN32 +#include <stdio.h> +#else +#include <dbg.h> +#endif + +static Bool +fbValidateBits (FbStip *bits, int stride, FbStip data) +{ + while (stride--) + { + if (*bits != data) + { +#ifdef WIN32 + NCD_DEBUG ((DEBUG_FAILURE, "fdValidateBits failed at 0x%x (is 0x%x want 0x%x)", + bits, *bits, data)); +#else + fprintf (stderr, "fbValidateBits failed\n"); +#endif + return FALSE; + } + bits++; + } +} + +void +fbValidateDrawable (DrawablePtr pDrawable) +{ + FbStip *bits, *first, *last; + int stride, bpp; + int xoff, yoff; + int height; + Bool failed; + + if (pDrawable->type != DRAWABLE_PIXMAP) + pDrawable = (DrawablePtr) fbGetWindowPixmap(pDrawable); + fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff); + first = bits - stride; + last = bits + stride * pDrawable->height; + if (!fbValidateBits (first, stride, FB_HEAD_BITS) || + !fbValidateBits (last, stride, FB_TAIL_BITS)) + fbInitializeDrawable(pDrawable); +} + +void +fbSetBits (FbStip *bits, int stride, FbStip data) +{ + while (stride--) + *bits++ = data; +} + +void +fbInitializeDrawable (DrawablePtr pDrawable) +{ + FbStip *bits, *first, *last; + int stride, bpp; + int xoff, yoff; + + fbGetStipDrawable(pDrawable, bits, stride, bpp, xoff, yoff); + first = bits - stride; + last = bits + stride * pDrawable->height; + fbSetBits (first, stride, FB_HEAD_BITS); + fbSetBits (last, stride, FB_TAIL_BITS); +} +#endif /* FB_DEBUG */ diff --git a/fb/fbpoint.c b/fb/fbpoint.c new file mode 100644 index 000000000..20426a9f1 --- /dev/null +++ b/fb/fbpoint.c @@ -0,0 +1,156 @@ +/* + * Id: fbpoint.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbpoint.c,v 1.8 2001/05/29 04:54:09 keithp Exp $ */ + +#include "fb.h" + +typedef void (*FbDots) (FbBits *dst, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint *pts, + int npt, + int xoff, + int yoff, + FbBits and, + FbBits xor); + +void +fbDots (FbBits *dstOrig, + FbStride dstStride, + int dstBpp, + BoxPtr pBox, + xPoint *pts, + int npt, + int xoff, + int yoff, + FbBits andOrig, + FbBits xorOrig) +{ + FbStip *dst = (FbStip *) dstOrig; + int x1, y1, x2, y2; + int x, y; + FbStip *d; + FbStip and = andOrig; + FbStip xor = xorOrig; + + dstStride = FbBitsStrideToStipStride (dstStride); + x1 = pBox->x1; + y1 = pBox->y1; + x2 = pBox->x2; + y2 = pBox->y2; + while (npt--) + { + x = pts->x + xoff; + y = pts->y + yoff; + pts++; + if (x1 <= x && x < x2 && y1 <= y && y < y2) + { + x *= dstBpp; + d = dst + (y * dstStride) + (x >> FB_STIP_SHIFT); + x &= FB_STIP_MASK; +#ifdef FB_24BIT + if (dstBpp == 24) + { + FbStip leftMask, rightMask; + int n, rot; + FbStip andT, xorT; + + rot = FbFirst24Rot (x); + andT = FbRot24Stip(and,rot); + xorT = FbRot24Stip(xor,rot); + FbMaskStip (x, 24, leftMask, n, rightMask); + if (leftMask) + { + *d = FbDoMaskRRop (*d, andT, xorT, leftMask); + andT = FbNext24Stip(andT); + xorT = FbNext24Stip(xorT); + d++; + } + if (rightMask) + *d = FbDoMaskRRop(*d, andT, xorT, rightMask); + } + else +#endif + { + FbStip mask; + mask = FbStipMask(x, dstBpp); + *d = FbDoMaskRRop (*d, and, xor, mask); + } + } + } +} + +void +fbPolyPoint (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int nptInit, + xPoint *pptInit) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + RegionPtr pClip = fbGetCompositeClip(pGC); + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbDots dots; + FbBits and, xor; + xPoint *ppt; + int npt; + BoxPtr pBox; + int nBox; + + /* make pointlist origin relative */ + ppt = pptInit; + npt = nptInit; + if (mode == CoordModePrevious) + { + npt--; + while(npt--) + { + ppt++; + ppt->x += (ppt-1)->x; + ppt->y += (ppt-1)->y; + } + } + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + and = pPriv->and; + xor = pPriv->xor; + dots = fbDots; +#ifndef FBNOPIXADDR + switch (dstBpp) { + case 8: dots = fbDots8; break; + case 16: dots = fbDots16; break; +#ifdef FB_24BIT + case 24: dots = fbDots24; break; +#endif + case 32: dots = fbDots32; break; + } +#endif + for (nBox = REGION_NUM_RECTS (pClip), pBox = REGION_RECTS (pClip); + nBox--; pBox++) + (*dots) (dst, dstStride, dstBpp, pBox, pptInit, nptInit, + pDrawable->x + dstXoff, pDrawable->y + dstYoff, and, xor); +} diff --git a/fb/fbpush.c b/fb/fbpush.c new file mode 100644 index 000000000..4ae60764c --- /dev/null +++ b/fb/fbpush.c @@ -0,0 +1,243 @@ +/* + * Id: fbpush.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbpush.c,v 1.5 2001/05/29 04:54:09 keithp Exp $ */ + +#include "fb.h" + +void +fbPushPattern (DrawablePtr pDrawable, + GCPtr pGC, + + FbStip *src, + FbStride srcStride, + int srcX, + + int x, + int y, + + int width, + int height) +{ + FbStip *s, bitsMask, bitsMask0, bits; + int xspan; + int w; + int lenspan; + + src += srcX >> FB_STIP_SHIFT; + srcX &= FB_STIP_MASK; + + bitsMask0 = FbStipMask (srcX, 1); + + while (height--) + { + bitsMask = bitsMask0; + w = width; + s = src; + src += srcStride; + bits = *s++; + xspan = x; + while (w) + { + if (bits & bitsMask) + { + lenspan = 0; + do + { + lenspan++; + if (lenspan == w) + break; + bitsMask = FbStipRight (bitsMask, 1); + if (!bitsMask) + { + bits = *s++; + bitsMask = FbBitsMask(0,1); + } + } while (bits & bitsMask); + fbFill (pDrawable, pGC, xspan, y, lenspan, 1); + xspan += lenspan; + w -= lenspan; + } + else + { + do + { + w--; + xspan++; + if (!w) + break; + bitsMask = FbStipRight (bitsMask, 1); + if (!bitsMask) + { + bits = *s++; + bitsMask = FbBitsMask(0,1); + } + } while (!(bits & bitsMask)); + } + } + y++; + } +} + +void +fbPushFill (DrawablePtr pDrawable, + GCPtr pGC, + + FbStip *src, + FbStride srcStride, + int srcX, + + int x, + int y, + int width, + int height) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + + if (pGC->fillStyle == FillSolid) + { + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + int dstX; + int dstWidth; + + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + dst = dst + (y + dstYoff) * dstStride; + dstX = (x + dstXoff) * dstBpp; + dstWidth = width * dstBpp; + if (dstBpp == 1) + { + fbBltStip (src, + srcStride, + srcX, + + (FbStip *) dst, + FbBitsStrideToStipStride (dstStride), + dstX, + + dstWidth, + height, + + FbStipple1Rop(pGC->alu,pGC->fgPixel), + pPriv->pm, + dstBpp); + } + else + { + fbBltOne (src, + srcStride, + srcX, + + dst, + dstStride, + dstX, + dstBpp, + + dstWidth, + height, + + pPriv->and, pPriv->xor, + fbAnd(GXnoop,(FbBits) 0,FB_ALLONES), + fbXor(GXnoop,(FbBits) 0,FB_ALLONES)); + } + } + else + { + fbPushPattern (pDrawable, pGC, src, srcStride, srcX, + x, y, width, height); + } +} + +void +fbPushImage (DrawablePtr pDrawable, + GCPtr pGC, + + FbStip *src, + FbStride srcStride, + int srcX, + + int x, + int y, + int width, + int height) +{ + RegionPtr pClip = fbGetCompositeClip (pGC); + int nbox; + BoxPtr pbox; + int x1, y1, x2, y2; + + for (nbox = REGION_NUM_RECTS (pClip), + pbox = REGION_RECTS(pClip); + nbox--; + pbox++) + { + x1 = x; + y1 = y; + x2 = x + width; + y2 = y + height; + if (x1 < pbox->x1) + x1 = pbox->x1; + if (y1 < pbox->y1) + y1 = pbox->y1; + if (x2 > pbox->x2) + x2 = pbox->x2; + if (y2 > pbox->y2) + y2 = pbox->y2; + if (x1 >= x2 || y1 >= y2) + continue; + fbPushFill (pDrawable, + pGC, + + src + (y1 - y) * srcStride, + srcStride, + srcX + (x1 - x), + + x1, + y1, + x2 - x1, + y2 - y1); + } +} + +void +fbPushPixels (GCPtr pGC, + PixmapPtr pBitmap, + DrawablePtr pDrawable, + int dx, + int dy, + int xOrg, + int yOrg) +{ + FbStip *stip; + FbStride stipStride; + int stipBpp; + int stipXoff, stipYoff; /* Assumed to be zero */ + + fbGetStipDrawable (&pBitmap->drawable, stip, stipStride, stipBpp, stipXoff, stipYoff); + + fbPushImage (pDrawable, pGC, + stip, stipStride, 0, + xOrg, yOrg, dx, dy); +} diff --git a/fb/fbrop.h b/fb/fbrop.h new file mode 100644 index 000000000..9481be680 --- /dev/null +++ b/fb/fbrop.h @@ -0,0 +1,139 @@ +/* + * Id: fbrop.h,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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbrop.h,v 1.4 2000/02/23 20:29:46 dawes Exp $ */ + +#ifndef _FBROP_H_ +#define _FBROP_H_ + +typedef struct _mergeRopBits { + FbBits ca1, cx1, ca2, cx2; +} FbMergeRopRec, *FbMergeRopPtr; + +extern const FbMergeRopRec FbMergeRopBits[16]; + +#define FbDeclareMergeRop() FbBits _ca1, _cx1, _ca2, _cx2; +#define FbDeclarePrebuiltMergeRop() FbBits _cca, _ccx; + +#define FbInitializeMergeRop(alu,pm) {\ + const FbMergeRopRec *_bits; \ + _bits = &FbMergeRopBits[alu]; \ + _ca1 = _bits->ca1 & pm; \ + _cx1 = _bits->cx1 | ~pm; \ + _ca2 = _bits->ca2 & pm; \ + _cx2 = _bits->cx2 & pm; \ +} + +#define FbDestInvarientRop(alu,pm) ((pm) == FB_ALLONES && \ + (((alu) >> 1 & 5) == ((alu) & 5))) + +#define FbDestInvarientMergeRop() (_ca1 == 0 && _cx1 == 0) + +/* AND has higher precedence than XOR */ + +#define FbDoMergeRop(src, dst) \ + (((dst) & (((src) & _ca1) ^ _cx1)) ^ (((src) & _ca2) ^ _cx2)) + +#define FbDoDestInvarientMergeRop(src) (((src) & _ca2) ^ _cx2) + +#define FbDoMaskMergeRop(src, dst, mask) \ + (((dst) & ((((src) & _ca1) ^ _cx1) | ~(mask))) ^ ((((src) & _ca2) ^ _cx2) & (mask))) + +#define FbDoLeftMaskByteMergeRop(dst, src, lb, l) { \ + FbBits __xor = ((src) & _ca2) ^ _cx2; \ + FbDoLeftMaskByteRRop(dst,lb,l,((src) & _ca1) ^ _cx1,__xor); \ +} + +#define FbDoRightMaskByteMergeRop(dst, src, rb, r) { \ + FbBits __xor = ((src) & _ca2) ^ _cx2; \ + FbDoRightMaskByteRRop(dst,rb,r,((src) & _ca1) ^ _cx1,__xor); \ +} + +#define FbDoRRop(dst, and, xor) (((dst) & (and)) ^ (xor)) + +#define FbDoMaskRRop(dst, and, xor, mask) \ + (((dst) & ((and) | ~(mask))) ^ (xor & mask)) + +/* + * Take a single bit (0 or 1) and generate a full mask + */ +#define fbFillFromBit(b,t) (~((t) ((b) & 1)-1)) + +#define fbXorT(rop,fg,pm,t) ((((fg) & fbFillFromBit((rop) >> 1,t)) | \ + (~(fg) & fbFillFromBit((rop) >> 3,t))) & (pm)) + +#define fbAndT(rop,fg,pm,t) ((((fg) & fbFillFromBit (rop ^ (rop>>1),t)) | \ + (~(fg) & fbFillFromBit((rop>>2) ^ (rop>>3),t))) | \ + ~(pm)) + +#define fbXor(rop,fg,pm) fbXorT(rop,fg,pm,FbBits) + +#define fbAnd(rop,fg,pm) fbAndT(rop,fg,pm,FbBits) + +#define fbXorStip(rop,fg,pm) fbXorT(rop,fg,pm,FbStip) + +#define fbAndStip(rop,fg,pm) fbAndT(rop,fg,pm,FbStip) + +/* + * Stippling operations; + */ + +extern const FbBits fbStipple16Bits[256]; /* half of table */ +#define FbStipple16Bits(b) \ + (fbStipple16Bits[(b)&0xff] | fbStipple16Bits[(b) >> 8] << FB_HALFUNIT) +extern const FbBits fbStipple8Bits[256]; +extern const FbBits fbStipple4Bits[16]; +extern const FbBits fbStipple2Bits[4]; +extern const FbBits fbStipple1Bits[2]; +extern const FbBits *const fbStippleTable[]; + +#define FbStippleRRop(dst, b, fa, fx, ba, bx) \ + (FbDoRRop(dst, fa, fx) & b) | (FbDoRRop(dst, ba, bx) & ~b) + +#define FbStippleRRopMask(dst, b, fa, fx, ba, bx, m) \ + (FbDoMaskRRop(dst, fa, fx, m) & (b)) | (FbDoMaskRRop(dst, ba, bx, m) & ~(b)) + +#define FbDoLeftMaskByteStippleRRop(dst, b, fa, fx, ba, bx, lb, l) { \ + FbBits __xor = ((fx) & (b)) | ((bx) & ~(b)); \ + FbDoLeftMaskByteRRop(dst, lb, l, ((fa) & (b)) | ((ba) & ~(b)), __xor); \ +} + +#define FbDoRightMaskByteStippleRRop(dst, b, fa, fx, ba, bx, rb, r) { \ + FbBits __xor = ((fx) & (b)) | ((bx) & ~(b)); \ + FbDoRightMaskByteRRop(dst, rb, r, ((fa) & (b)) | ((ba) & ~(b)), __xor); \ +} + +#define FbOpaqueStipple(b, fg, bg) (((fg) & (b)) | ((bg) & ~(b))) + +/* + * Compute rop for using tile code for 1-bit dest stipples; modifies + * existing rop to flip depending on pixel values + */ +#define FbStipple1RopPick(alu,b) (((alu) >> (2 - (((b) & 1) << 1))) & 3) + +#define FbOpaqueStipple1Rop(alu,fg,bg) (FbStipple1RopPick(alu,fg) | \ + (FbStipple1RopPick(alu,bg) << 2)) + +#define FbStipple1Rop(alu,fg) (FbStipple1RopPick(alu,fg) | 4) + +#endif diff --git a/fb/fbscreen.c b/fb/fbscreen.c new file mode 100644 index 000000000..bdcc9d139 --- /dev/null +++ b/fb/fbscreen.c @@ -0,0 +1,297 @@ +/* + * Id: fbscreen.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbscreen.c,v 1.13 2001/05/29 04:54:09 keithp Exp $ */ + +#include "fb.h" + +Bool +fbCloseScreen (int index, ScreenPtr pScreen) +{ + int d; + DepthPtr depths = pScreen->allowedDepths; + + for (d = 0; d < pScreen->numDepths; d++) + xfree (depths[d].vids); + xfree (depths); + xfree (pScreen->visuals); + xfree (pScreen->devPrivate); +#ifdef FB_SCREEN_PRIVATE + xfree (pScreen->devPrivates[fbScreenPrivateIndex].ptr); +#endif + return TRUE; +} + +Bool +fbRealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + return (TRUE); +} + +Bool +fbUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + return (TRUE); +} + +void +fbQueryBestSize (int class, + unsigned short *width, unsigned short *height, + ScreenPtr pScreen) +{ + unsigned short w; + + switch (class) { + case CursorShape: + if (*width > pScreen->width) + *width = pScreen->width; + if (*height > pScreen->height) + *height = pScreen->height; + break; + case TileShape: + case StippleShape: + w = *width; + if ((w & (w - 1)) && w < FB_UNIT) + { + for (w = 1; w < *width; w <<= 1) + ; + *width = w; + } + } +} + +#ifndef FB_OLD_SCREEN +PixmapPtr +_fbGetWindowPixmap (WindowPtr pWindow) +{ + return fbGetWindowPixmap (pWindow); +} + +void +_fbSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap) +{ +#ifdef FB_NO_WINDOW_PIXMAPS + FatalError ("Attempted to set window pixmap without fb support\n"); +#else + pWindow->devPrivates[fbWinPrivateIndex].ptr = (pointer) pPixmap; +#endif +} +#endif + +Bool +fbSetupScreen(ScreenPtr pScreen, + pointer pbits, /* pointer to screen bitmap */ + int xsize, /* in pixels */ + int ysize, + int dpix, /* dots per inch */ + int dpiy, + int width, /* pixel width of frame buffer */ + int bpp) /* bits per pixel for screen */ +{ + if (!fbAllocatePrivates(pScreen, (int *) 0)) + return FALSE; + pScreen->defColormap = FakeClientID(0); + /* let CreateDefColormap do whatever it wants for pixels */ + pScreen->blackPixel = pScreen->whitePixel = (Pixel) 0; + pScreen->QueryBestSize = fbQueryBestSize; + /* SaveScreen */ + pScreen->GetImage = fbGetImage; + pScreen->GetSpans = fbGetSpans; + pScreen->CreateWindow = fbCreateWindow; + pScreen->DestroyWindow = fbDestroyWindow; + pScreen->PositionWindow = fbPositionWindow; + pScreen->ChangeWindowAttributes = fbChangeWindowAttributes; + pScreen->RealizeWindow = fbMapWindow; + pScreen->UnrealizeWindow = fbUnmapWindow; + pScreen->PaintWindowBackground = fbPaintWindow; + pScreen->PaintWindowBorder = fbPaintWindow; + pScreen->CopyWindow = fbCopyWindow; + pScreen->CreatePixmap = fbCreatePixmap; + pScreen->DestroyPixmap = fbDestroyPixmap; + pScreen->RealizeFont = fbRealizeFont; + pScreen->UnrealizeFont = fbUnrealizeFont; + pScreen->CreateGC = fbCreateGC; + pScreen->CreateColormap = fbInitializeColormap; + pScreen->DestroyColormap = (void (*)(ColormapPtr))NoopDDA; + pScreen->InstallColormap = fbInstallColormap; + pScreen->UninstallColormap = fbUninstallColormap; + pScreen->ListInstalledColormaps = fbListInstalledColormaps; + pScreen->StoreColors = (void (*)(ColormapPtr, int, xColorItem *))NoopDDA; + pScreen->ResolveColor = fbResolveColor; + pScreen->BitmapToRegion = fbPixmapToRegion; + +#ifndef FB_OLD_SCREEN + pScreen->GetWindowPixmap = _fbGetWindowPixmap; + pScreen->SetWindowPixmap = _fbSetWindowPixmap; + + pScreen->BackingStoreFuncs.SaveAreas = fbSaveAreas; + pScreen->BackingStoreFuncs.RestoreAreas = fbRestoreAreas; + pScreen->BackingStoreFuncs.SetClipmaskRgn = 0; + pScreen->BackingStoreFuncs.GetImagePixmap = 0; + pScreen->BackingStoreFuncs.GetSpansPixmap = 0; +#endif + + return TRUE; +} + +Bool +fbFinishScreenInit(ScreenPtr pScreen, + pointer pbits, + int xsize, + int ysize, + int dpix, + int dpiy, + int width, + int bpp) +{ + VisualPtr visuals; + DepthPtr depths; + int nvisuals; + int ndepths; + int rootdepth; + VisualID defaultVisual; + int imagebpp = bpp; + +#ifdef FB_DEBUG + int stride; + + ysize -= 2; + stride = (width * bpp) / 8; + fbSetBits ((FbStip *) pbits, + stride / sizeof (FbStip), FB_HEAD_BITS); + pbits = (void *) ((char *) pbits + stride); + fbSetBits ((FbStip *) ((char *) pbits + stride * ysize), + stride / sizeof (FbStip), FB_TAIL_BITS); +#endif + /* + * By default, a 24bpp screen will use 32bpp images, this avoids + * problems with many applications which just can't handle packed + * pixels. If you want real 24bit images, include a 24bpp + * format in the pixmap formats + */ +#ifdef FB_24_32BIT + if (bpp == 24) + { + int f; + + imagebpp = 32; + /* + * Check to see if we're advertising a 24bpp image format, + * in which case windows will use it in preference to a 32 bit + * format. + */ + for (f = 0; f < screenInfo.numPixmapFormats; f++) + { + if (screenInfo.formats[f].bitsPerPixel == 24) + { + imagebpp = 24; + break; + } + } + } +#endif +#ifdef FB_SCREEN_PRIVATE + if (imagebpp == 32) + { + fbGetScreenPrivate(pScreen)->win32bpp = bpp; + fbGetScreenPrivate(pScreen)->pix32bpp = bpp; + } + else + { + fbGetScreenPrivate(pScreen)->win32bpp = 32; + fbGetScreenPrivate(pScreen)->pix32bpp = 32; + } +#endif + rootdepth = 0; + if (!fbInitVisuals (&visuals, &depths, &nvisuals, &ndepths, &rootdepth, + &defaultVisual,((unsigned long)1<<(imagebpp-1)), 8)) + return FALSE; + if (! miScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width, + rootdepth, ndepths, depths, + defaultVisual, nvisuals, visuals +#ifdef FB_OLD_SCREEN + , (miBSFuncPtr) 0 +#endif + )) + return FALSE; + /* overwrite miCloseScreen with our own */ + pScreen->CloseScreen = fbCloseScreen; +#ifdef FB_24_32BIT + if (bpp == 24 && imagebpp == 32) + { + pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader; + pScreen->CreateScreenResources = fb24_32CreateScreenResources; + } +#endif +#if 0 + /* leave backing store initialization to the enclosing code so + * it can choose the correct order of wrappers + */ + /* init backing store here so we can overwrite CloseScreen without stepping + * on the backing store wrapped version */ + fbInitializeBackingStore (pScreen); +#endif + return TRUE; +} + +/* dts * (inch/dot) * (25.4 mm / inch) = mm */ +Bool +fbScreenInit(ScreenPtr pScreen, + pointer pbits, + int xsize, + int ysize, + int dpix, + int dpiy, + int width, + int bpp) +{ + if (!fbSetupScreen(pScreen, pbits, xsize, ysize, dpix, dpiy, width, bpp)) + return FALSE; + if (!fbFinishScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, + width, bpp)) + return FALSE; + return TRUE; +} + + +#ifdef FB_OLD_SCREEN +const miBSFuncRec fbBSFuncRec = { + fbSaveAreas, + fbRestoreAreas, + (void (*)(GCPtr, RegionPtr)) 0, + (PixmapPtr (*)(void)) 0, + (PixmapPtr (*)(void)) 0, +}; +#endif + +#if 0 +void +fbInitializeBackingStore (ScreenPtr pScreen) +{ +#ifdef FB_OLD_SCREEN + miInitializeBackingStore (pScreen, (miBSFuncRec *) &fbBSFuncRec); +#else + miInitializeBackingStore (pScreen); +#endif +} +#endif diff --git a/fb/fbseg.c b/fb/fbseg.c new file mode 100644 index 000000000..284f11fa9 --- /dev/null +++ b/fb/fbseg.c @@ -0,0 +1,723 @@ +/* + * Id: fbseg.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbseg.c,v 1.8 2001/05/29 04:54:09 keithp Exp $ */ + +#include "fb.h" +#include "miline.h" + +#define fbBresShiftMask(mask,dir,bpp) ((bpp == FB_STIP_UNIT) ? 0 : \ + ((dir < 0) ? FbStipLeft(mask,bpp) : \ + FbStipRight(mask,bpp))) + +void +fbBresSolid (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbStip and = (FbStip) pPriv->and; + FbStip xor = (FbStip) pPriv->xor; + FbStip mask, mask0; + FbStip bits; + + fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * dstBpp; + dst += x1 >> FB_STIP_SHIFT; + x1 &= FB_STIP_MASK; + mask0 = FbStipMask(0, dstBpp); + mask = FbStipRight (mask0, x1); + if (signdx < 0) + mask0 = FbStipRight (mask0, FB_STIP_UNIT - dstBpp); + if (signdy < 0) + dstStride = -dstStride; + if (axis == X_AXIS) + { + bits = 0; + while (len--) + { + bits |= mask; + mask = fbBresShiftMask(mask,signdx,dstBpp); + if (!mask) + { + *dst = FbDoMaskRRop (*dst, and, xor, bits); + bits = 0; + dst += signdx; + mask = mask0; + } + e += e1; + if (e >= 0) + { + *dst = FbDoMaskRRop (*dst, and, xor, bits); + bits = 0; + dst += dstStride; + e += e3; + } + } + if (bits) + *dst = FbDoMaskRRop (*dst, and, xor, bits); + } + else + { + while (len--) + { + *dst = FbDoMaskRRop (*dst, and, xor, mask); + dst += dstStride; + e += e1; + if (e >= 0) + { + e += e3; + mask = fbBresShiftMask(mask,signdx,dstBpp); + if (!mask) + { + dst += signdx; + mask = mask0; + } + } + } + } +} + +void +fbBresDash (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbStip and = (FbStip) pPriv->and; + FbStip xor = (FbStip) pPriv->xor; + FbStip bgand = (FbStip) pPriv->bgand; + FbStip bgxor = (FbStip) pPriv->bgxor; + FbStip mask, mask0; + FbDashDeclare; + int dashlen; + Bool even; + Bool doOdd; + + fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + doOdd = pGC->lineStyle == LineDoubleDash; + + FbDashInit (pGC, pPriv, dashOffset, dashlen, even); + + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * dstBpp; + dst += x1 >> FB_STIP_SHIFT; + x1 &= FB_STIP_MASK; + mask0 = FbStipMask(0, dstBpp); + mask = FbStipRight (mask0, x1); + if (signdx < 0) + mask0 = FbStipRight (mask0, FB_STIP_UNIT - dstBpp); + if (signdy < 0) + dstStride = -dstStride; + while (len--) + { + if (even) + *dst = FbDoMaskRRop (*dst, and, xor, mask); + else if (doOdd) + *dst = FbDoMaskRRop (*dst, bgand, bgxor, mask); + if (axis == X_AXIS) + { + mask = fbBresShiftMask(mask,signdx,dstBpp); + if (!mask) + { + dst += signdx; + mask = mask0; + } + e += e1; + if (e >= 0) + { + dst += dstStride; + e += e3; + } + } + else + { + dst += dstStride; + e += e1; + if (e >= 0) + { + e += e3; + mask = fbBresShiftMask(mask,signdx,dstBpp); + if (!mask) + { + dst += signdx; + mask = mask0; + } + } + } + FbDashStep (dashlen, even); + } +} + +void +fbBresFill (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + while (len--) + { + fbFill (pDrawable, pGC, x1, y1, 1, 1); + if (axis == X_AXIS) + { + x1 += signdx; + e += e1; + if (e >= 0) + { + e += e3; + y1 += signdy; + } + } + else + { + y1 += signdy; + e += e1; + if (e >= 0) + { + e += e3; + x1 += signdx; + } + } + } +} + +static void +fbSetFg (DrawablePtr pDrawable, + GCPtr pGC, + Pixel fg) +{ + if (fg != pGC->fgPixel) + { + DoChangeGC (pGC, GCForeground, (XID *) &fg, FALSE); + ValidateGC (pDrawable, pGC); + } +} + +void +fbBresFillDash (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbDashDeclare; + int dashlen; + Bool even; + Bool doOdd; + Bool doBg; + Pixel fg, bg; + + fg = pGC->fgPixel; + bg = pGC->bgPixel; + + /* whether to fill the odd dashes */ + doOdd = pGC->lineStyle == LineDoubleDash; + /* whether to switch fg to bg when filling odd dashes */ + doBg = doOdd && (pGC->fillStyle == FillSolid || + pGC->fillStyle == FillStippled); + + /* compute current dash position */ + FbDashInit (pGC, pPriv, dashOffset, dashlen, even); + + while (len--) + { + if (even || doOdd) + { + if (doBg) + { + if (even) + fbSetFg (pDrawable, pGC, fg); + else + fbSetFg (pDrawable, pGC, bg); + } + fbFill (pDrawable, pGC, x1, y1, 1, 1); + } + if (axis == X_AXIS) + { + x1 += signdx; + e += e1; + if (e >= 0) + { + e += e3; + y1 += signdy; + } + } + else + { + y1 += signdy; + e += e1; + if (e >= 0) + { + e += e3; + x1 += signdx; + } + } + FbDashStep (dashlen, even); + } + if (doBg) + fbSetFg (pDrawable, pGC, fg); +} + +#ifdef FB_24BIT +static void +fbBresSolid24RRop (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbStip and = pPriv->and; + FbStip xor = pPriv->xor; + FbStip leftMask, rightMask; + int nl; + FbStip *d; + int x; + int rot; + FbStip andT, xorT; + + fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * 24; + if (signdy < 0) + dstStride = -dstStride; + signdx *= 24; + while (len--) + { + d = dst + (x1 >> FB_STIP_SHIFT); + x = x1 & FB_STIP_MASK; + rot = FbFirst24Rot (x); + andT = FbRot24Stip(and,rot); + xorT = FbRot24Stip(xor,rot); + FbMaskStip (x, 24, leftMask, nl, rightMask); + if (leftMask) + { + *d = FbDoMaskRRop (*d, andT, xorT, leftMask); + d++; + andT = FbNext24Stip (andT); + xorT = FbNext24Stip (xorT); + } + if (rightMask) + *d = FbDoMaskRRop (*d, andT, xorT, rightMask); + if (axis == X_AXIS) + { + x1 += signdx; + e += e1; + if (e >= 0) + { + e += e3; + dst += dstStride; + } + } + else + { + dst += dstStride; + e += e1; + if (e >= 0) + { + e += e3; + x1 += signdx; + } + } + } +} + +static void +fbBresDash24RRop (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + FbStip *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + FbStip andT, xorT; + FbStip fgand = pPriv->and; + FbStip fgxor = pPriv->xor; + FbStip bgand = pPriv->bgand; + FbStip bgxor = pPriv->bgxor; + FbStip leftMask, rightMask; + int nl; + FbStip *d; + int x; + int rot; + FbDashDeclare; + int dashlen; + Bool even; + Bool doOdd; + + fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + doOdd = pGC->lineStyle == LineDoubleDash; + + /* compute current dash position */ + FbDashInit(pGC, pPriv, dashOffset, dashlen, even); + + dst += ((y1 + dstYoff) * dstStride); + x1 = (x1 + dstXoff) * 24; + if (signdy < 0) + dstStride = -dstStride; + signdx *= 24; + while (len--) + { + if (even || doOdd) + { + if (even) + { + andT = fgand; + xorT = fgxor; + } + else + { + andT = bgand; + xorT = bgxor; + } + d = dst + (x1 >> FB_STIP_SHIFT); + x = x1 & FB_STIP_MASK; + rot = FbFirst24Rot (x); + andT = FbRot24Stip (andT, rot); + xorT = FbRot24Stip (xorT, rot); + FbMaskStip (x, 24, leftMask, nl, rightMask); + if (leftMask) + { + *d = FbDoMaskRRop (*d, andT, xorT, leftMask); + d++; + andT = FbNext24Stip (andT); + xorT = FbNext24Stip (xorT); + } + if (rightMask) + *d = FbDoMaskRRop (*d, andT, xorT, rightMask); + } + if (axis == X_AXIS) + { + x1 += signdx; + e += e1; + if (e >= 0) + { + e += e3; + dst += dstStride; + } + } + else + { + dst += dstStride; + e += e1; + if (e >= 0) + { + e += e3; + x1 += signdx; + } + } + FbDashStep (dashlen, even); + } +} +#endif + +/* + * For drivers that want to bail drawing some lines, this + * function takes care of selecting the appropriate rasterizer + * based on the contents of the specified GC. + */ + +FbBres * +fbSelectBres (DrawablePtr pDrawable, + GCPtr pGC) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); + int dstBpp = pDrawable->bitsPerPixel; + FbBres * bres; + + if (pGC->lineStyle == LineSolid) + { + bres = fbBresFill; + if (pGC->fillStyle == FillSolid) + { + bres = fbBresSolid; +#ifdef FB_24BIT + if (dstBpp == 24) + bres = fbBresSolid24RRop; +#endif +#ifndef FBNOPIXADDR + if (pPriv->and == 0) + { + switch (dstBpp) { + case 8: bres = fbBresSolid8; break; + case 16: bres = fbBresSolid16; break; +#ifdef FB_24BIT + case 24: bres = fbBresSolid24; break; +#endif + case 32: bres = fbBresSolid32; break; + } + } +#endif + } + } + else + { + bres = fbBresFillDash; + if (pGC->fillStyle == FillSolid) + { + bres = fbBresDash; +#ifdef FB_24BIT + if (dstBpp == 24) + bres = fbBresDash24RRop; +#endif +#ifndef FBNOPIXADDR + if (pPriv->and == 0 && + (pGC->lineStyle == LineOnOffDash || pPriv->bgand == 0)) + { + switch (dstBpp) { + case 8: bres = fbBresDash8; break; + case 16: bres = fbBresDash16; break; +#ifdef FB_24BIT + case 24: bres = fbBresDash24; break; +#endif + case 32: bres = fbBresDash32; break; + } + } +#endif + } + } + return bres; +} + +void +fbBres (DrawablePtr pDrawable, + GCPtr pGC, + int dashOffset, + int signdx, + int signdy, + int axis, + int x1, + int y1, + int e, + int e1, + int e3, + int len) +{ + (*fbSelectBres (pDrawable, pGC)) (pDrawable, pGC, dashOffset, + signdx, signdy, axis, x1, y1, + e, e1, e3, len); +} + +void +fbSegment (DrawablePtr pDrawable, + GCPtr pGC, + int x1, + int y1, + int x2, + int y2, + Bool drawLast, + int *dashOffset) +{ + FbBres * bres; + 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, e3; /* bresenham error and increments */ + int len; /* length of segment */ + int axis; /* major axis */ + int octant; + int dashoff; + int doff; + unsigned int bias = miGetZeroLineBias(pDrawable->pScreen); + unsigned int oc1; /* outcode of point 1 */ + unsigned int oc2; /* outcode of point 2 */ + + nBox = REGION_NUM_RECTS (pClip); + pBox = REGION_RECTS (pClip); + + bres = fbSelectBres (pDrawable, pGC); + + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, + 1, 1, octant); + + if (adx > ady) + { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + len = adx; + } + else + { + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + SetYMajorOctant(octant); + len = ady; + } + + FIXUP_ERROR (e, octant, bias); + + /* + * Adjust error terms to compare against zero + */ + e3 = e2 - e1; + e = e - e1; + + /* we have bresenham parameters and two points. + all we have to do now is clip and draw. + */ + + if (drawLast) + len++; + dashoff = *dashOffset; + *dashOffset = dashoff + len; + while(nBox--) + { + oc1 = 0; + oc2 = 0; + OUTCODES(oc1, x1, y1, pBox); + OUTCODES(oc2, x2, y2, pBox); + if ((oc1 | oc2) == 0) + { + (*bres) (pDrawable, pGC, dashoff, + signdx, signdy, axis, x1, y1, + e, e1, e3, 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 */ + doff = dashoff; + err = e; + if (clip1) + { + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + if (axis == X_AXIS) + { + doff += clipdx; + err += e3 * clipdy + e1 * clipdx; + } + else + { + doff += clipdy; + err += e3 * clipdx + e1 * clipdy; + } + } + (*bres) (pDrawable, pGC, doff, + signdx, signdy, axis, new_x1, new_y1, + err, e1, e3, len); + } + pBox++; + } + } /* while (nBox--) */ +} diff --git a/fb/fbsetsp.c b/fb/fbsetsp.c new file mode 100644 index 000000000..e207760c6 --- /dev/null +++ b/fb/fbsetsp.c @@ -0,0 +1,100 @@ +/* + * Id: fbsetsp.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbsetsp.c,v 1.5 2001/05/29 04:54:09 keithp Exp $ */ + +#include "fb.h" + +void +fbSetSpans (DrawablePtr pDrawable, + GCPtr pGC, + char *src, + DDXPointPtr ppt, + int *pwidth, + int nspans, + int fSorted) +{ + FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); + RegionPtr pClip = fbGetCompositeClip(pGC); + FbBits *dst, *d, *s; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + BoxPtr pbox; + int n; + int xoff; + int x1, x2; + +#ifdef FB_24_32BIT + if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) + { + fb24_32SetSpans (pDrawable, pGC, src, ppt, pwidth, nspans, fSorted); + return; + } +#endif + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + while (nspans--) + { + d = dst + (ppt->y + dstYoff) * dstStride; + xoff = (int) (((long) src) & (FB_MASK >> 3)); + s = (FbBits *) (src - xoff); + xoff <<= 3; + n = REGION_NUM_RECTS(pClip); + pbox = REGION_RECTS (pClip); + while (n--) + { + if (pbox->y1 > ppt->y) + break; + if (pbox->y2 > ppt->y) + { + x1 = ppt->x; + x2 = x1 + *pwidth; + if (pbox->x1 > x1) + x1 = pbox->x1; + if (pbox->x2 < x2) + x2 = pbox->x2; + if (x1 < x2) + fbBlt ((FbBits *) s, + 0, + (x1 - ppt->x) * dstBpp + xoff, + d, + dstStride, + (x1 + dstXoff) * dstBpp, + + (x2 - x1) * dstBpp, + 1, + pGC->alu, + pPriv->pm, + dstBpp, + + FALSE, + FALSE); + } + } + src += PixmapBytePad (*pwidth, pDrawable->depth); + ppt++; + pwidth++; + } + fbValidateDrawable (pDrawable); +} + diff --git a/fb/fbsolid.c b/fb/fbsolid.c new file mode 100644 index 000000000..17b5bffe0 --- /dev/null +++ b/fb/fbsolid.c @@ -0,0 +1,212 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fbsolid.c,v 1.8 2001/10/28 03:33:08 tsi 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. + */ + +#define FbSelectPart(xor,o,t) xor + +#include "fb.h" + +void +fbSolid (FbBits *dst, + FbStride dstStride, + int dstX, + int bpp, + + int width, + int height, + + FbBits and, + FbBits xor) +{ + FbBits startmask, endmask; + int n, nmiddle; + int startbyte, endbyte; + +#ifdef FB_24BIT + if (bpp == 24 && (!FbCheck24Pix(and) || !FbCheck24Pix(xor))) + { + fbSolid24 (dst, dstStride, dstX, width, height, and, xor); + return; + } +#endif + + dst += dstX >> FB_SHIFT; + dstX &= FB_MASK; + FbMaskBitsBytes(dstX, width, and == 0, startmask, startbyte, + nmiddle, endmask, endbyte); + if (startmask) + dstStride--; + dstStride -= nmiddle; + while (height--) + { + if (startmask) + { + FbDoLeftMaskByteRRop(dst,startbyte,startmask,and,xor); + dst++; + } + n = nmiddle; + if (!and) + while (n--) + *dst++ = xor; + else + while (n--) + { + *dst = FbDoRRop (*dst, and, xor); + dst++; + } + if (endmask) + FbDoRightMaskByteRRop(dst,endbyte,endmask,and,xor); + dst += dstStride; + } +} + +#ifdef FB_24BIT +void +fbSolid24 (FbBits *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + FbBits and, + FbBits xor) +{ + FbBits startmask, endmask; + FbBits xor0 = 0, xor1 = 0, xor2 = 0; + FbBits and0 = 0, and1 = 0, and2 = 0; + FbBits xorS = 0, andS = 0, xorE = 0, andE = 0; + int n, nmiddle; + int rotS, rot; + + dst += dstX >> FB_SHIFT; + dstX &= FB_MASK; + /* + * Rotate pixel values this far across the word to align on + * screen pixel boundaries + */ + rot = FbFirst24Rot (dstX); + FbMaskBits (dstX, width, startmask, nmiddle, endmask); + if (startmask) + dstStride--; + dstStride -= nmiddle; + + /* + * Precompute rotated versions of the rasterop values + */ + rotS = rot; + xor = FbRot24(xor,rotS); + and = FbRot24(and,rotS); + if (startmask) + { + xorS = xor; + andS = and; + xor = FbNext24Pix(xor); + and = FbNext24Pix(and); + } + + if (nmiddle) + { + xor0 = xor; + and0 = and; + xor1 = FbNext24Pix(xor0); + and1 = FbNext24Pix(and0); + xor2 = FbNext24Pix(xor1); + and2 = FbNext24Pix(and1); + } + + if (endmask) + { + switch (nmiddle % 3) { + case 0: + xorE = xor; + andE = and; + break; + case 1: + xorE = xor1; + andE = and1; + break; + case 2: + xorE = xor2; + andE = and2; + break; + } + } + + while (height--) + { + if (startmask) + { + *dst = FbDoMaskRRop(*dst, andS, xorS, startmask); + dst++; + } + n = nmiddle; + if (!and0) + { + while (n >= 3) + { + *dst++ = xor0; + *dst++ = xor1; + *dst++ = xor2; + n -= 3; + } + if (n) + { + *dst++ = xor0; + n--; + if (n) + { + *dst++ = xor1; + } + } + } + else + { + while (n >= 3) + { + *dst = FbDoRRop (*dst, and0, xor0); + dst++; + *dst = FbDoRRop (*dst, and1, xor1); + dst++; + *dst = FbDoRRop (*dst, and2, xor2); + dst++; + n -= 3; + } + if (n) + { + *dst = FbDoRRop (*dst, and0, xor0); + dst++; + n--; + if (n) + { + *dst = FbDoRRop (*dst, and1, xor1); + dst++; + } + } + } + if (endmask) + *dst = FbDoMaskRRop (*dst, andE, xorE, endmask); + dst += dstStride; + } +} +#endif diff --git a/fb/fbstipple.c b/fb/fbstipple.c new file mode 100644 index 000000000..88f694bb8 --- /dev/null +++ b/fb/fbstipple.c @@ -0,0 +1,312 @@ +/* + * 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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbstipple.c,v 1.7 2001/10/28 03:33:08 tsi Exp $ */ + +#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 + */ + fbBits = 0; /* unused */ + if (pixelsPerDst <= 8) + fbBits = fbStippleTable[pixelsPerDst]; + + while (height--) + { + /* + * Extract stipple bits for this scanline; + */ + bits = *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--) + *dst++ = xor; + else + { + while (n--) + { + *dst = FbDoRRop (*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); +} diff --git a/fb/fbtile.c b/fb/fbtile.c new file mode 100644 index 000000000..ed447f8d3 --- /dev/null +++ b/fb/fbtile.c @@ -0,0 +1,200 @@ +/* + * Id: fbtile.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbtile.c,v 1.4 2000/02/23 20:29:48 dawes Exp $ */ + +#include "fb.h" + +/* + * Accelerated tile fill -- tile width is a power of two not greater + * than FB_UNIT + */ + +void +fbEvenTile (FbBits *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + FbBits *tile, + int tileHeight, + + int alu, + FbBits pm, + int xRot, + int yRot) +{ + FbBits *t, *tileEnd, bits; + FbBits startmask, endmask; + FbBits and, xor; + int n, nmiddle; + int tileX, tileY; + int rot; + int startbyte, endbyte; + + dst += dstX >> FB_SHIFT; + dstX &= FB_MASK; + FbMaskBitsBytes(dstX, width, FbDestInvarientRop(alu, pm), + startmask, startbyte, nmiddle, endmask, endbyte); + if (startmask) + dstStride--; + dstStride -= nmiddle; + + /* + * Compute tile start scanline and rotation parameters + */ + tileEnd = tile + tileHeight; + modulus (- yRot, tileHeight, tileY); + t = tile + tileY; + modulus (- xRot, FB_UNIT, tileX); + rot = tileX; + + while (height--) + { + + /* + * Pick up bits for this scanline + */ + bits = *t++; + if (t == tileEnd) t = tile; + bits = FbRotLeft(bits,rot); + and = fbAnd(alu,bits,pm); + xor = fbXor(alu,bits,pm); + + if (startmask) + { + FbDoLeftMaskByteRRop(dst, startbyte, startmask, and, xor); + dst++; + } + n = nmiddle; + if (!and) + while (n--) + *dst++ = xor; + else + while (n--) + { + *dst = FbDoRRop (*dst, and, xor); + dst++; + } + if (endmask) + FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor); + dst += dstStride; + } +} + +void +fbOddTile(FbBits *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + FbBits *tile, + FbStride tileStride, + int tileWidth, + int tileHeight, + + int alu, + FbBits pm, + int bpp, + + int xRot, + int yRot) +{ + int tileX, tileY; + int widthTmp; + int h, w; + int x, y; + + modulus (- yRot, tileHeight, tileY); + y = 0; + while (height) + { + h = tileHeight - tileY; + if (h > height) + h = height; + height -= h; + widthTmp = width; + x = dstX; + modulus (dstX - xRot, tileWidth, tileX); + while (widthTmp) + { + w = tileWidth - tileX; + if (w > widthTmp) + w = widthTmp; + widthTmp -= w; + fbBlt (tile + tileY * tileStride, + tileStride, + tileX, + + dst + y * dstStride, + dstStride, + x, + + w, h, + alu, + pm, + bpp, + + FALSE, + FALSE); + x += w; + tileX = 0; + } + y += h; + tileY = 0; + } +} + +void +fbTile (FbBits *dst, + FbStride dstStride, + int dstX, + + int width, + int height, + + FbBits *tile, + FbStride tileStride, + int tileWidth, + int tileHeight, + + int alu, + FbBits pm, + int bpp, + + int xRot, + int yRot) +{ + if (FbEvenTile (tileWidth)) + fbEvenTile (dst, dstStride, dstX, width, height, + tile, tileHeight, + alu, pm, xRot, yRot); + else + fbOddTile (dst, dstStride, dstX, width, height, + tile, tileStride, tileWidth, tileHeight, + alu, pm, bpp, xRot, yRot); +} diff --git a/fb/fbtrap.c b/fb/fbtrap.c new file mode 100644 index 000000000..3a44d53ef --- /dev/null +++ b/fb/fbtrap.c @@ -0,0 +1,1382 @@ +/* + * $XFree86: xc/programs/Xserver/fb/fbtrap.c,v 1.10 2002/09/27 00:31:24 keithp Exp $ + * + * Copyright © 2000 University of Southern California + * + * 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 University + * of Southern California not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. University of Southern California makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * University of Southern California 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: Carl Worth, USC, Information Sciences Institute */ + +#include "fb.h" + +#ifdef RENDER + +#include "picturestr.h" +#include "mipict.h" +#include "fbpict.h" + +#ifdef DEBUG +#include <stdio.h> +#include <assert.h> + +#define ASSERT(e) assert(e) + +#endif + +#ifndef ASSERT +#define ASSERT(e) +#endif + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define MAX_AREA 0x80000000 + +/* + * A RationalPoint is an exact position along one of the trapezoid + * edges represented by an approximate position (x,y) and two error + * terms (ex_dy, ey_dx). The error in X is multiplied by the Y + * dimension of the line while the error in Y is multiplied by the + * X dimension of the line, allowing an exact measurement of the + * distance from (x,y) to the line. + * + * Generally, while walking an edge, one of ex_dy/ey_dx will be zero + * indicating that the position error is held in the other. + */ +typedef struct { + xFixed x; + xFixed ex_dy; + xFixed y; + xFixed ey_dx; +} RationalPoint; + +/* + * Edges are walked both horizontally and vertically + * They are walked vertically to get to a particular row + * of pixels, and then walked horizontally within that row + * to compute pixel coverage. + * + * Edges are always walked from top to bottom and from + * left to right. This means that for lines moving leftwards + * from top to bottom, the left to right walking actually moves + * backwards along the line with respect to the top to bottom + * walking. + */ + +/* + * A RationalRow represents the two positions where + * an edge intersects a row of pixels. This is used + * to walk an edge vertically + */ + +typedef struct { + RationalPoint top; /* intersection at top of row */ + RationalPoint bottom; /* intersection at bottom of row */ + RationalPoint pixel_top; /* intersection at top of pixel */ +} RationalRow; + +/* + * A RationalCol represents the two positions where + * an edge intersects a column of pixels + */ + +typedef struct { + RationalPoint left; /* intersection at left of column */ + RationalPoint right; /* intersection at right of column */ +} RationalCol; + +/* + Here are some thoughts on line walking: + + Conditions: c2.x - c1.x = 1 + r2.y - r1.y = 1 + + A B C D E F G H + c1\ c1 c2 /c2 +r1 r1 |\ \ r1 r1 / r1/| r1 r1 +\-+---+ \-+---+ +-\-+ +\--+ +--/+ +-/-+ +---+-/ +---+-/ + \| | `.c1 | |r1\| | \ | | / | |/ | | .' | |/ +c1\ | |`-.|c2 | \c2 | | | | | | c1/ | c1|,_/|c2 | /c2 + |\ | | `. | |\ | \ | | / | /| | ./ | | /| + +-\-+ +---+-\ +---+-\ +--\+ +/--+ /-+---+ /-+---+ +-/-+ + r2\| r2 r2 r2\ /r2 r2 r2 |/r2 + \c2 c2 c1 c1/ + + Bottom Right Right Bottom Top Top Right Right + +State transitions: + +A -> C, D E -> E, F +B -> A, B F -> G, H +C -> A, B G -> G, H +D -> C, D H -> E, F + +*/ + +/* + * Values for PixelWalk.depart. Top and Bottom can have the same value + * as only one mode is possible given a line of either positive or + * negative slope. These mark the departure edge while walking + * rightwards across columns. + */ + +typedef enum _departure { + DepartTop = 0, /* edge exits top of pixel */ + DepartBottom = 0, /* edge exits bottom of pixel */ + DepartRight = 1 /* edge exits right edge of pixel */ +} Departure; + +/* + * PixelWalk + * + * This structure holds state to walk a single edge down the trapezoid. + * + * The edge is walked twice -- once by rows and once by columns. + * The two intersections of the pixel by the edge are then set + * from either the row or column position, depending on which edge + * is intersected. + * + * Note that for lines moving left, walking by rows moves down the + * line (increasing y) while walking by columns moves up the line + * (decreasing y). + */ +typedef struct { + xFixed dx; + xFixed ey_thresh; + xFixed dy; + xFixed ex_thresh; + + Departure depart; + + /* slope */ + xFixed m; + xFixed em_dx; + xFixed y_correct; + xFixed ey_correct; + + /* Inverse slope. Does this have a standard symbol? */ + xFixed p; + xFixed ep_dy; + xFixed x_correct; + xFixed ex_correct; + + /* Trapezoid bottom, used to limit walking to the last row */ + xFixed bottom; + + /* + * Current edge positions along pixel rows and columns + */ + RationalRow row; + RationalCol col; + + /* + * The three pixel intersection points, copied from the appropriate + * row or column position above + */ + RationalPoint p_pixel_top; + RationalPoint p_trap_top; + RationalPoint p_trap_bottom; +} PixelWalk; + +#if 0 +#ifdef GCC +#define INLINE inline +#endif +#endif + +#ifndef INLINE +#define INLINE +#endif + +/* + * Step 'pt' vertically to 'newy'. + */ +static INLINE void +pixelWalkMovePointToRow (PixelWalk *pw, RationalPoint *pt, xFixed newy) +{ + xFixed_32_32 oex; + xFixed xoff; + + /* X error of old X position and new Y position */ + oex = (xFixed_32_32) pw->dx * (newy - pt->y) - pt->ey_dx + pt->ex_dy; + + /* amount to step X by */ + xoff = oex / pw->dy; + + /* step X */ + pt->x = pt->x + xoff; + + /* set new X error value for new X position and new Y positition */ + pt->ex_dy = oex - (xFixed_32_32) pw->dy * xoff; + + /* set new Y position, set Y error to zero */ + pt->y = newy; + pt->ey_dx = 0; +} + +/* + * Step 'pt' horizontally to 'newx' + */ +static INLINE void +pixelWalkMovePointToCol (PixelWalk *pw, RationalPoint *pt, xFixed newx) +{ + xFixed_32_32 oey; + xFixed yoff; + + /* Special case vertical lines to arbitrary y */ + if (pw->dx == 0) + { + pt->x = newx; + pt->ex_dy = 0; + pt->y = 0; + pt->ey_dx = 0; + } + else + { + /* Y error of old Y position and new X position */ + oey = (xFixed_32_32) pw->dy * (newx - pt->x) - pt->ex_dy + pt->ey_dx; + + /* amount to step Y by */ + yoff = oey / pw->dx; + + /* step Y */ + pt->y = pt->y + yoff; + + /* set new Y error value for new Y position and new X position */ + pt->ey_dx = oey - (xFixed_32_32) pw->dx * yoff; + + /* set new X position, set X error to zero */ + pt->x = newx; + pt->ex_dy = 0; + } +} + +/* + * Step the 'row' element of 'pw' vertically + * (increasing y) by one whole pixel + */ +static INLINE void +pixelWalkStepRow (PixelWalk *pw) +{ + xFixed y_next = xFixedFloor (pw->row.bottom.y) + xFixed1; + + if (y_next > pw->bottom) + y_next = pw->bottom; + + /* pw.row.top.y < pw.row.bottom.y */ + pw->row.top = pw->row.bottom; + + if (y_next - pw->row.bottom.y == xFixed1) + { + pw->row.pixel_top = pw->row.bottom; + pw->row.bottom.y += xFixed1; + pw->row.bottom.x += pw->p; + pw->row.bottom.ex_dy += pw->ep_dy; + if (abs (pw->row.bottom.ex_dy) > pw->ex_thresh) + { + pw->row.bottom.x += pw->x_correct; + pw->row.bottom.ex_dy += pw->ex_correct; + } + } + else + { + pixelWalkMovePointToRow (pw, &pw->row.pixel_top, + xFixedCeil (y_next) - xFixed1); + pixelWalkMovePointToRow (pw, &pw->row.bottom, y_next); + } +} + +/* + * Step the 'col' element of 'pw' horizontally + * (increasing x) by one whole pixel + */ +static INLINE void +pixelWalkStepCol (PixelWalk *pw) +{ + /* pw.col.p1.x < pw.col.p2.x */ + /* + * Copy the current right point into the left point + */ + pw->col.left = pw->col.right; + + /* + * Now incrementally walk across the pixel + */ + pw->col.right.x += xFixed1; + pw->col.right.y += pw->m; + pw->col.right.ey_dx += pw->em_dx; + if (pw->col.right.ey_dx > pw->ey_thresh) + { + pw->col.right.y += pw->y_correct; + pw->col.right.ey_dx += pw->ey_correct; + } +} +/* + * Walk to the nearest edge of the next pixel, filling in both p1 and + * p2 as necessary from either the row or col intersections. + * + * The "next" pixel is defined to be the next pixel intersected by the + * line with pixels visited in raster scan order, (for the benefit of + * cache performance). For lines with positive slope it is easy to + * achieve raster scan order by simply calling StepCol for each pixel + * in a given scanline, then calling StepRow once at the end of each + * scanline. + * + * However, for lines of negative slope where the magnitude of dx is + * greater than dy, a little more work needs to be done. The pixels of + * a particular scanline will be visited by succesive calls to StepCol + * as before. This will effectively step "up" the line as we scan from + * left to right. But, the call to StepRow at the end of the scan line + * will step "down" the line and the column information will be + * invalid at that point. + * + * For now, I fix up the column of all negative slope lines by calling + * MovePointToCol at the end of each scanline. However, this is an + * extremely expensive operation since it involves a 64-bit multiply + * and a 64-bit divide. It would be much better, (at least as long as + * abs(dx) is not much greater than dy), to instead step the col + * backwards as many times as necessary. Or even better, we could + * simply restore col to the position it began at when we started the + * scanline, then simply step it backwards once. That would give a + * performance benefit for lines with slope of any magnitude. + */ + +static INLINE void +pixelWalkNextPixel (PixelWalk *pw) +{ + if (pw->dx < 0) + { + /* + * left moving lines + * + * Check which pixel edge we're departing from + * + * Remember that in this case (dx < 0), the 'row' element of 'pw' + * walks down the line while 'col' walks up + */ + if (pw->depart == DepartTop) + { + /* + * The edge departs the row at this pixel, the + * next time it gets used will be for the next row + * + * Step down one row and then recompute the + * column values to start the next row of + * pixels + */ + pixelWalkStepRow(pw); + /* + * Set column exit pixel + */ + pixelWalkMovePointToCol(pw, &pw->col.right, xFixedFloor(pw->row.bottom.x)); + /* + * This moves the exit pixel to the entry pixel + * and computes the next exit pixel + */ + pixelWalkStepCol(pw); + /* + * The first pixel on the next row will always + * be entered from below, set the lower + * intersection of this edge with that pixel + */ + pw->p_trap_bottom = pw->row.bottom; + } + else /* pw->depart == DepartRight */ + { + /* + * easy case -- just move right one pixel + */ + pixelWalkStepCol(pw); + /* + * Set the lower intersection of the edge with the + * pixel -- that's just where the edge entered + * the pixel from the left + */ + pw->p_trap_bottom = pw->col.left; + } + /* + * Now compute which edge the pixel + * is departing from + */ + if (pw->row.top.x <= pw->col.right.x) + { + /* + * row intersection is left of column intersection, + * that means the edge hits the top of the pixel + * before it hits the right edge + */ + pw->p_trap_top = pw->row.top; + pw->depart = DepartTop; + /* + * Further check to see whether the edge + * leaves the right or top edge of the + * whole pixel + */ + if (pw->row.pixel_top.x <= pw->col.right.x) + pw->p_pixel_top = pw->row.pixel_top; + else + pw->p_pixel_top = pw->col.right; + } + else + { + /* + * Row intersection is right of colum intersection, + * that means the edge hits the right edge of the + * pixel first + */ + pw->p_trap_top = pw->col.right; + pw->p_pixel_top = pw->col.right; + pw->depart = DepartRight; + } + } + else + { + /* + * right moving lines + * + * Check which edge we're departing from + * + * In the dx >= 0 case, the row and col elements both + * walk downwards + */ + if (pw->depart == DepartBottom) + { + /* + * The edge departs the row at this pixel, + * the next time it gets used will be for the + * next row + * + * Step down one row and (maybe) over one + * column to prepare for the next row + */ + if (pw->row.bottom.x == pw->col.right.x) + { + /* + * right through the corner of the pixel, + * adjust the column + */ + pixelWalkStepCol(pw); + } + pixelWalkStepRow(pw); + /* + * Set the upper intersection of the edge with + * the pixel, the first pixel on the next + * row is always entered from the top + */ + pw->p_trap_top = pw->row.top; + pw->p_pixel_top = pw->row.pixel_top; + } + else /* pw->depart == DepartRight */ + { + /* + * Easy case -- move right one + * pixel + */ + pixelWalkStepCol(pw); + /* + * Set the upper intersection of the edge + * with the pixel, that's along the left + * edge of the pixel + */ + pw->p_trap_top = pw->col.left; + pw->p_pixel_top = pw->col.left; + } + /* + * Now compute the exit edge and the + * lower intersection of the edge with the pixel + */ + if (pw->row.bottom.x <= pw->col.right.x) + { + /* + * Hit the place where the edge leaves + * the pixel, the lower intersection is + * where the edge hits the bottom + */ + pw->p_trap_bottom = pw->row.bottom; + pw->depart = DepartBottom; + } + else + { + /* + * The edge goes through the + * next pixel on the row, + * the lower intersection is where the + * edge hits the right side of the pixel + */ + pw->p_trap_bottom = pw->col.right; + pw->depart = DepartRight; + } + } +} + +/* + * Compute the first pixel intersection points + * and the departure type from that pixel + */ +static void +pixelWalkFirstPixel (PixelWalk *pw) +{ + if (pw->dx < 0) + { + if (pw->row.top.x <= pw->col.right.x) + { + /* + * leaving through the top. + * upper position is the upper point of + * the 'row' element + */ + pw->depart = DepartTop; + pw->p_trap_top = pw->row.top; + /* + * further check for pixel top + */ + if (pw->row.pixel_top.x <= pw->col.right.x) + pw->p_pixel_top = pw->row.pixel_top; + else + pw->p_pixel_top = pw->col.right; + } + else + { + /* + * leaving through the right side + * upper position is the right point of + * the 'col' element + */ + pw->depart = DepartRight; + pw->p_trap_top = pw->col.right; + pw->p_pixel_top = pw->col.right; + } + /* + * Now find the lower pixel intersection point + */ + if (pw->row.bottom.x >= pw->col.left.x) + /* + * entering through bottom, + * lower position is the bottom point of + * the 'row' element + */ + pw->p_trap_bottom = pw->row.bottom; + else + /* + * entering through left side, + * lower position is the left point of + * the 'col' element + */ + pw->p_trap_bottom = pw->col.left; + } + else + { + if (pw->row.bottom.x <= pw->col.right.x) + { + /* + * leaving through the bottom (or corner). + * lower position is the lower point of + * the 'row' element + */ + pw->depart = DepartBottom; + pw->p_trap_bottom = pw->row.bottom; + } + else + { + /* + * leaving through the right side + * lower position is the right point of + * the 'col' element + */ + pw->depart = DepartRight; + pw->p_trap_bottom = pw->col.right; + } + /* + * Now find the upper pixel intersection point + */ + if (pw->row.top.x >= pw->col.left.x) + { + /* + * entering through the top (or corner), + * upper position is the top point + * of the 'row' element + */ + pw->p_trap_top = pw->row.top; + /* + * further check for pixel entry + */ + if (pw->row.pixel_top.x >= pw->col.left.x) + pw->p_pixel_top = pw->row.pixel_top; + else + pw->p_pixel_top = pw->col.left; + } + else + { + /* + * entering through the left side, + * upper position is the left point of + * the 'col' element + */ + pw->p_trap_top = pw->col.left; + pw->p_pixel_top = pw->col.left; + } + } +} + +static void +pixelWalkInit (PixelWalk *pw, xLineFixed *line, xFixed top_y, xFixed bottom_y) +{ + xFixed_32_32 dy_inc, dx_inc; + xFixed next_y; + xFixed left_x; + xPointFixed *top, *bot; + + next_y = xFixedFloor (top_y) + xFixed1; + if (next_y > bottom_y) + next_y = bottom_y; + + /* + * Orient lines top down + */ + if (line->p1.y < line->p2.y) + { + top = &line->p1; + bot = &line->p2; + } + else + { + top = &line->p2; + bot = &line->p1; + } + + pw->dx = bot->x - top->x; + pw->ey_thresh = abs(pw->dx >> 1); + pw->dy = bot->y - top->y; + pw->ex_thresh = pw->dy >> 1; + + /* + * Set step values for walking lines + */ + if (pw->dx < 0) + { + pw->x_correct = -1; + pw->ex_correct = pw->dy; + pw->y_correct = -1; + pw->ey_correct = pw->dx; + } + else + { + pw->x_correct = 1; + pw->ex_correct = -pw->dy; + pw->y_correct = 1; + pw->ey_correct = -pw->dx; + } + + pw->bottom = bottom_y; + + /* + * Compute Bresenham values for walking edges incrementally + */ + dy_inc = (xFixed_32_32) xFixed1 * pw->dy; /* > 0 */ + if (pw->dx != 0) + { + pw->m = dy_inc / pw->dx; /* sign(dx) */ + pw->em_dx = dy_inc - (xFixed_32_32) pw->m * pw->dx; /* > 0 */ + } + else + { + /* Vertical line. Setting these to zero prevents us from + having to put any conditions in pixelWalkStepCol. */ + pw->m = 0; + pw->em_dx = 0; + } + + dx_inc = (xFixed_32_32) xFixed1 * (xFixed_32_32) pw->dx; /* sign(dx) */ + pw->p = dx_inc / pw->dy; /* sign(dx) */ + pw->ep_dy = dx_inc - (xFixed_32_32) pw->p * pw->dy; /* sign(dx) */ + + /* + * Initialize 'row' for walking down rows + */ + pw->row.bottom.x = top->x; + pw->row.bottom.ex_dy = 0; + pw->row.bottom.y = top->y; + pw->row.bottom.ey_dx = 0; + + /* + * Initialize 'pixel_top' to be on the line for + * the first step + */ + pw->row.pixel_top = pw->row.bottom; + /* + * Move to the pixel above the 'top_y' coordinate, + * first setting 'bottom' and then using StepRow + * which moves that to 'top' and computes the next 'bottom' + */ + pixelWalkMovePointToRow(pw, &pw->row.bottom, top_y); + pixelWalkStepRow(pw); + + /* + * Initialize 'col' for walking across columns + */ + pw->col.right.x = top->x; + pw->col.right.ex_dy = 0; + pw->col.right.y = top->y; + pw->col.right.ey_dx = 0; + + /* + * First set the column to the left most + * pixel hit by the row + */ + if (pw->dx < 0) + left_x = pw->row.bottom.x; + else + left_x = pw->row.top.x; + + pixelWalkMovePointToCol(pw, &pw->col.right, xFixedFloor (left_x)); + pixelWalkStepCol(pw); + + /* + * Compute first pixel intersections and the + * first departure state + */ + pixelWalkFirstPixel (pw); +} + +#define RoundShift(a,b) (((a) + (1 << ((b) - 1))) >> (b)) +#define MaxAlpha(depth) ((1 << (depth)) - 1) + +#define AreaAlpha(area, depth) (RoundShift (RoundShift (area, depth) * \ + MaxAlpha (depth), \ + (31 - depth))) + +/* + Pixel coverage from the upper-left corner bounded by one horizontal + bottom line (bottom) and one line defined by two points, (x1,y1) and + (x2,y2), which intersect the pixel. y1 must be less than y2. There + are 8 cases yielding the following area calculations: + + A B C D E F G H ++---+ +---+ +-1-+ +1--+ +--1+ +-1-+ +---+ +---+ +| | 1 | | \| | \ | | / | |/ | | 1 | | +1 | |`-.| | 2 | | | | | | 2 | |,_/| | 1 +|\ | | 2 | | | \ | | / | | | 2 | | /| ++-2-+ +---+ +---+ +--2+ +2--+ +---+ +---+ +-2-+ + +A: (1/2 * x2 * (y2 - y1)) +B: (1/2 * x2 * (y2 - y1)) + (bottom - y2) * x2 +C: (1/2 * (x1 + x2) * y2 ) + (bottom - y2) * x2 +D: (1/2 * (x1 + x2) * y2 ) +E: (1/2 * (x1 + x2) * y2 ) +F: (1/2 * x1 * y2 ) +G: (1/2 * x1 * (y2 - y1)) + x1 * y1 +H: (1/2 * (x1 + x2) * (y2 - y1)) + x1 * y1 + +The union of these calculations is valid for all cases. Namely: + + (1/2 * (x1 + x2) * (y2 - y1)) + (bottom - y2) * x2 + x1 * y1 + +An exercise for later would perhaps be to optimize the calculations +for some of the cases above. Specifically, it's possible to eliminate +multiplications by zero in several cases, leaving a maximum of two +multiplies per pixel calculation. (This is even more promising now +that the higher level code actually computes the exact same 8 cases +as part of its pixel walking). + +But, for now, I just want to get something working correctly even if +slower. So, we'll use the non-optimized general equation. + +*/ + +/* 1.16 * 1.16 -> 1.31 */ +#define AREA_MULT(w, h) ( (xFixed_1_31) (((((xFixed_1_16)w)*((xFixed_1_16)h) + 1) >> 1) | (((xFixed_1_16)w)&((xFixed_1_16)h)&0x10000) << 15)) + +/* (1.16 + 1.16) / 2 -> 1.16 */ +#define WIDTH_AVG(x1,x2) (((x1) + (x2) + 1) >> 1) + +#define SubPixelArea(x1, y1, x2, y2, bottom) \ +(xFixed_1_31) ( \ + AREA_MULT((x1), (y1)) \ + + AREA_MULT(WIDTH_AVG((x1), (x2)), (y2) - (y1))\ + + AREA_MULT((x2), (bottom) - (y2)) \ +) + +/* +static xFixed_1_31 +SubPixelArea (xFixed_1_16 x1, + xFixed_1_16 y1, + xFixed_1_16 x2, + xFixed_1_16 y2, + xFixed_1_16 bottom) +{ + xFixed_1_16 x_trap; + xFixed_1_16 h_top, h_trap, h_bot; + xFixed_1_31 area; + + x_trap = WIDTH_AVG(x1,x2); + h_top = y1; + h_trap = (y2 - y1); + h_bot = (bottom - y2); + + area = AREA_MULT(x1, h_top) + + AREA_MULT(x_trap, h_trap) + + AREA_MULT(x2, h_bot); + + return area; +} +*/ + +#define SubPixelAlpha(x1, y1, x2, y2, bottom, depth) \ +( \ + AreaAlpha( \ + SubPixelArea((x1), (y1), (x2), (y2), (bottom)), \ + (depth) \ + ) \ +) + +/* +static int +SubPixelAlpha (xFixed_1_16 x1, + xFixed_1_16 y1, + xFixed_1_16 x2, + xFixed_1_16 y2, + xFixed_1_16 bottom, + int depth) +{ + xFixed_1_31 area; + + area = SubPixelArea(x1, y1, x2, y2, bottom); + + return AreaAlpha(area, depth); +} +*/ + +/* Alpha of a pixel above a given horizontal line */ +#define AlphaAbove(pixel_y, line_y, depth) \ +( \ + AreaAlpha(AREA_MULT((line_y) - (pixel_y), xFixed1), depth) \ +) + +static int +RectAlpha(xFixed pixel_y, xFixed top, xFixed bottom, int depth) +{ + if (depth == 1) + return top == pixel_y ? 1 : 0; + else + return (AlphaAbove (pixel_y, bottom, depth) - + AlphaAbove (pixel_y, top, depth)); +} + + +/* + * Pixel coverage from the left edge bounded by one horizontal lines, + * (top and bottom), as well as one PixelWalk line. + */ +static int +AlphaAboveLeft(RationalPoint *upper, + RationalPoint *lower, + xFixed bottom, + xFixed pixel_x, + xFixed pixel_y, + int depth) +{ + return SubPixelAlpha(upper->x - pixel_x, + upper->y - pixel_y, + lower->x - pixel_x, + lower->y - pixel_y, + bottom - pixel_y, + depth); +} + +/* + Pixel coverage from the left edge bounded by two horizontal lines, + (top and bottom), as well as one line two points, p1 and p2, which + intersect the pixel. The following condition must be true: + + p2.y > p1.y +*/ + +/* + lr + |\ + +--|-\-------+ + | a| b\ | + =======|===\========== top + | c| d \ | + =======|=====\======== bot + | | \ | + +--|-------\-+ + + alpha(d) = alpha(cd) - alpha(c) = alpha(abcd) - alpha(ab) - (alpha(ac) - alpha(c)) + + alpha(d) = pixelalpha(top, bot, right) - pixelalpha(top, bot, left) + + pixelalpha(top, bot, line) = subpixelalpha(bot, line) - subpixelalpha(top, line) +*/ + +static int +PixelAlpha(xFixed pixel_x, + xFixed pixel_y, + xFixed top, + xFixed bottom, + PixelWalk *pw, + int depth) +{ + int alpha; + +#ifdef DEBUG + fprintf(stderr, "alpha (%f, %f) - (%f, %f) = ", + (double) pw->p1.x / (1 << 16), + (double) pw->p1.y / (1 << 16), + (double) pw->p2.x / (1 << 16), + (double) pw->p2.y / (1 << 16)); + fflush(stderr); +#endif + + /* + * Sharp polygons are different, alpha is 1 if the + * area includes the pixel origin, else zero, in + * the above figure, only 'a' has alpha 1 + */ + if (depth == 1) + { + alpha = 0; + if (top == pixel_y && pw->p_pixel_top.x != pixel_x) + alpha = 1; + } + else + { + alpha = (AlphaAboveLeft(&pw->p_pixel_top, &pw->p_trap_bottom, + bottom, pixel_x, pixel_y, depth) + - AlphaAboveLeft(&pw->p_pixel_top, &pw->p_trap_top, + top, pixel_x, pixel_y, depth)); + } + +#ifdef DEBUG + fprintf(stderr, "0x%x => %f\n", + alpha, + (double) alpha / ((1 << depth) -1 )); + fflush(stderr); +#endif + + return alpha; +} + +#define INCREMENT_X_AND_PIXEL \ +{ \ + pixel_x += xFixed1; \ + (*mask.over) (&mask); \ +} + +/* XXX: What do we really want this prototype to look like? Do we want + separate versions for 1, 4, 8, and 16-bit alpha? */ + +#define saturateAdd(t, a, b) (((t) = (a) + (b)), \ + ((CARD8) ((t) | (0 - ((t) >> 8))))) + +#define addAlpha(mask, depth, alpha, temp) (\ + (*(mask)->store) ((mask), (alpha == (1 << depth) - 1) ? \ + 0xff000000 : \ + (saturateAdd (temp, \ + alpha << (8 - depth), \ + (*(mask)->fetch) (mask) >> 24) << 24)) \ +) + +void +fbRasterizeTrapezoid (PicturePtr pMask, + xTrapezoid *pTrap, + int x_off, + int y_off) +{ + xTrapezoid trap = *pTrap; + int alpha, temp; + + FbCompositeOperand mask; + + int depth = pMask->pDrawable->depth; + int max_alpha = (1 << depth) - 1; + int buf_width = pMask->pDrawable->width; + + xFixed x_off_fixed = IntToxFixed(x_off); + xFixed y_off_fixed = IntToxFixed(y_off); + xFixed buf_width_fixed = IntToxFixed(buf_width); + + PixelWalk left, right; + xFixed pixel_x, pixel_y; + xFixed first_right_x; + xFixed y, y_next; + + /* trap.left and trap.right must be non-horizontal */ + if (trap.left.p1.y == trap.left.p2.y + || trap.right.p1.y == trap.right.p2.y) { + return; + } + + trap.top += y_off_fixed; + trap.bottom += y_off_fixed; + trap.left.p1.x += x_off_fixed; + trap.left.p1.y += y_off_fixed; + trap.left.p2.x += x_off_fixed; + trap.left.p2.y += y_off_fixed; + trap.right.p1.x += x_off_fixed; + trap.right.p1.y += y_off_fixed; + trap.right.p2.x += x_off_fixed; + trap.right.p2.y += y_off_fixed; + +#ifdef DEBUG + fprintf(stderr, "(top, bottom) = (%f, %f)\n", + (double) trap.top / (1 << 16), + (double) trap.bottom / (1 << 16)); +#endif + + pixelWalkInit(&left, &trap.left, trap.top, trap.bottom); + pixelWalkInit(&right, &trap.right, trap.top, trap.bottom); + + /* XXX: I'd still like to optimize this loop for top and + bottom. Only the first row intersects top and only the last + row, (which could also be the first row), intersects bottom. So + we could eliminate some unnecessary calculations from all other + rows. Unfortunately, I haven't found an easy way to do it + without bloating the text, (eg. unrolling a couple iterations + of the loop). So, for sake of maintenance, I'm putting off this + optimization at least until this code is more stable.. */ + + if (!fbBuildCompositeOperand (pMask, &mask, 0, xFixedToInt (trap.top), FALSE, FALSE)) + return; + + for (y = trap.top; y < trap.bottom; y = y_next) + { + pixel_y = xFixedFloor (y); + y_next = pixel_y + xFixed1; + if (y_next > trap.bottom) + y_next = trap.bottom; + + ASSERT (left.row.top.y == y); + ASSERT (left.row.bottom.y == y_next); + ASSERT (right.row.top.y == y); + ASSERT (right.row.bottom.y == y_next); + + pixel_x = xFixedFloor(left.col.left.x); + + /* + * Walk pixels on this row that are left of the + * first possibly lit pixel + * + * pixelWalkNextPixel will change .row.top.y + * when the last pixel covered by the edge + * is passed + */ + + first_right_x = xFixedFloor(right.col.left.x); + while (right.row.top.y == y && first_right_x < pixel_x) + { + /* these are empty */ + pixelWalkNextPixel (&right); + /* step over */ + first_right_x += xFixed1; + } + + (*mask.set) (&mask, xFixedToInt (pixel_x), xFixedToInt (y)); + + /* + * Walk pixels on this row intersected by only trap.left + * + */ + while (left.row.top.y == y && pixel_x < first_right_x) + { + alpha = (RectAlpha (pixel_y, y, y_next, depth) + - PixelAlpha(pixel_x, pixel_y, y, y_next, &left, depth)); + + if (alpha > 0) + { + if (0 <= pixel_x && pixel_x < buf_width_fixed) + addAlpha (&mask, depth, alpha, temp); + } + + /* + * Step right + */ + pixelWalkNextPixel(&left); + INCREMENT_X_AND_PIXEL; + } + + /* + * Either pixels are covered by both edges or + * there are fully covered pixels on this row + */ + if (pixel_x == first_right_x) + { + /* + * Now walk the pixels on this row intersected + * by both edges + */ + while (left.row.top.y == y && right.row.top.y == y) + { + alpha = (PixelAlpha(pixel_x, pixel_y, y, y_next, &right, depth) + - PixelAlpha(pixel_x, pixel_y, y, y_next, &left, depth)); + if (alpha > 0) + { + ASSERT (0 <= alpha && alpha <= max_alpha); + if (0 <= pixel_x && pixel_x < buf_width_fixed) + addAlpha (&mask, depth, alpha, temp); + } + pixelWalkNextPixel(&left); + pixelWalkNextPixel(&right); + INCREMENT_X_AND_PIXEL; + } + /* + * If the right edge is now left of the left edge, + * the left edge will end up only partially walked, + * walk it the rest of the way + */ + while (left.row.top.y == y) + pixelWalkNextPixel(&left); + } + else + { + /* + * Fully covered pixels simply saturate + */ + alpha = RectAlpha (pixel_y, y, y_next, depth); + if (alpha == max_alpha) + { + while (pixel_x < first_right_x) + { + if (0 <= pixel_x && pixel_x < buf_width_fixed) + (*mask.store) (&mask, 0xff000000); + INCREMENT_X_AND_PIXEL; + } + } + else + { + while (pixel_x < first_right_x) + { + ASSERT (0 <= alpha && alpha <= max_alpha); + if (0 <= pixel_x && pixel_x < buf_width_fixed) + addAlpha (&mask, depth, alpha, temp); + INCREMENT_X_AND_PIXEL; + } + } + } + + /* + * Finally, pixels intersected only by trap.right + */ + while (right.row.top.y == y) + { + alpha = PixelAlpha(pixel_x, pixel_y, y, y_next, &right, depth); + if (alpha > 0) + { + if (0 <= pixel_x && pixel_x < buf_width_fixed) + addAlpha (&mask, depth, alpha, temp); + } + pixelWalkNextPixel(&right); + INCREMENT_X_AND_PIXEL; + } + } +} + +/* Some notes on walking while keeping track of errors in both dimensions: + +That's really pretty easy. Your bresenham should be walking sub-pixel +coordinates rather than pixel coordinates. Now you can calculate the +sub-pixel Y coordinate for any arbitrary sub-pixel X coordinate (or vice +versa). + + ey: y error term (distance from current Y sub-pixel to line) * dx + ex: x error term (distance from current X sub-pixel to line) * dy + dx: difference of X coordinates for line endpoints + dy: difference of Y coordinates for line endpoints + x: current fixed-point X coordinate + y: current fixed-point Y coordinate + +One of ey or ex will always be zero, depending on whether the distance to +the line was measured horizontally or vertically. + +In moving from x, y to x1, y1: + + (x1 + e1x/dy) - (x + ex/dy) dx + --------------------------- = -- + (y1 + e1y/dx) - (y + ey/dx) dy + + (x1dy + e1x) - (xdy + ex) = (y1dx + e1y) - (ydx + ey) + + dy(x1 - x) + (e1x - ex) = dx(y1-y) + (e1y - ey) + +So, if you know y1 and want to know x1: + + Set e1y to zero and compute the error from x: + + oex = dx(y1 - y) - ey + ex + + Compute the number of whole pixels to get close to the line: + + wx = oex / dy + + Set x1: + + Now compute the e1x: + + e1x = oex - wx * dy + +A similar operation moves to a known y1. Note that this computation (in +general) requires 64 bit arithmetic. I suggest just using the available +64 bit datatype for now, we can optimize the common cases with a few +conditionals. There's some cpp code in fb/fb.h that selects a 64 bit type +for machines that XFree86 builds on; there aren't any machines missing a +64 bit datatype that I know of. +*/ + +/* Here's a large-step Bresenham for jogging my memory. + +void large_bresenham_x_major(x1, y1, x2, y2, x_inc) +{ + int x, y, dx, dy, m; + int em_dx, ey_dx; + + dx = x2 - x1; + dy = y2 - y1; + + m = (x_inc * dy) / dx; + em_dx = (x_inc * dy) - m * dx; + + x = x1; + y = y1; + ey = 0; + + set(x,y); + + while (x < x2) { + x += x_inc; + y += m; + ey_dx += em_dx; + if (ey_dx > dx_2) { + y++; + ey_dx -= dx; + } + set(x,y); + } +} + +*/ + +/* Here are the latest, simplified equations for computing trapezoid + coverage of a pixel: + + alpha_from_area(A) = round(2**depth-1 * A) + + alpha(o) = 2**depth-1 + + alpha(a) = alpha_from_area(area(a)) + + alpha(ab) = alpha_from_area(area(ab)) + + alpha(b) = alpha(ab) - alpha (a) + + alpha(abc) = alpha_from_area(area(abc)) + + alpha(c) = alpha(abc) - alpha(ab) + + alpha(ad) = alpha_from_area(area(ad)) + + alpha (d) = alpha(ad) - alpha (a) + + alpha (abde) = alpha_from_area(area(abde)) + + alpha (de) = alpha (abde) - alpha (ab) + + alpha (e) = alpha (de) - alpha (d) + + alpha (abcdef) = alpha_from_area(area(abcdef)) + + alpha (def) = alpha (abcdef) - alpha (abc) + + alpha (f) = alpha (def) - alpha (de) + + alpha (adg) = alpha_from_area(area(adg)) + + alpha (g) = alpha (adg) - alpha (ad) + + alpha (abdegh) = alpha_from_area(area(abdegh)) + + alpha (gh) = alpha (abdegh) - alpha (abde) + + alpha (h) = alpha (gh) - alpha (g) + + alpha (abcdefghi) = alpha_from_area(area(abcdefghi)) = + alpha_from_area(area(o)) = alpha_from_area(1) = alpha(o) + + alpha (ghi) = alpha (abcdefghi) - alpha (abcdef) + + alpha (i) = alpha (ghi) - alpha (gh) +*/ + +/* Latest thoughts from Keith on implementing area/alpha computations: + +*** 1.16 * 1.16 -> 1.31 *** +#define AREA_MULT(w,h) ((w)&(h) == 0x10000 ? 0x80000000 : (((w)*(h) + 1) >> 1) + +*** (1.16 + 1.16) / 2 -> 1.16 *** +#define WIDTH_AVG(x1,x2) (((x1) + (x2) + 1) >> 1) + +xFixed_1_31 +SubpixelArea (xFixed_1_16 x1, + xFixed_1_16 x2, + xFixed_1_16 y1, + xFixed_1_16 y2, + xFixed_1_16 bottom) + { + xFixed_1_16 x_trap; + xFixed_1_16 h_top, h_trap, h_bot; + xFixed_1_31 area; + + x_trap = WIDTH_AVG(x1,x2); + h_top = y1; + h_trap = (y2 - y1); + h_bot = (bottom - y2); + + area = AREA_MULT(x1, h_top) + + AREA_MULT(x_trap, h_trap) + + AREA_MULT(x2, h_bot); + + return area; + } + +To convert this xFixed_1_31 value to alpha using 32 bit arithmetic: + +int +AreaAlpha (xFixed_1_31 area, int depth) + { + return ((area >> bits) * ((1 << depth) - 1)) >> (31 - depth); + } + +Avoiding the branch bubble in the AREA_MULT could be done with either: + +area = (w * h + 1) >> 1; +area |= ((area - 1) & 0x80000000); + +or + #define AREA_MULT(w,h) ((((w)*(h) + 1) >> 1) | ((w)&(h)&0x10000) << 15) + +depending on your preference, the first takes one less operation but +can't be expressed as a macro; the second takes a large constant which may +require an additional instruction on some processors. The differences +will be swamped by the cost of the multiply. + +*/ + +#endif /* RENDER */ diff --git a/fb/fbutil.c b/fb/fbutil.c new file mode 100644 index 000000000..54b88ad7e --- /dev/null +++ b/fb/fbutil.c @@ -0,0 +1,361 @@ +/* + * Id: fbutil.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbutil.c,v 1.5 2001/03/28 14:37:03 alanh Exp $ */ + +#include "fb.h" + +FbBits +fbReplicatePixel (Pixel p, int bpp) +{ + FbBits b = p; + + b &= FbFullMask (bpp); + while (bpp < FB_UNIT) + { + b |= b << bpp; + bpp <<= 1; + } + return b; +} + +void +fbReduceRasterOp (int rop, FbBits fg, FbBits pm, FbBits *andp, FbBits *xorp) +{ + FbBits and, xor; + + switch (rop) + { + default: + case GXclear: /* 0 0 0 0 */ + and = 0; + xor = 0; + break; + case GXand: /* 0 0 0 1 */ + and = fg; + xor = 0; + break; + case GXandReverse: /* 0 0 1 0 */ + and = fg; + xor = fg; + break; + case GXcopy: /* 0 0 1 1 */ + and = 0; + xor = fg; + break; + case GXandInverted: /* 0 1 0 0 */ + and = ~fg; + xor = 0; + break; + case GXnoop: /* 0 1 0 1 */ + and = FB_ALLONES; + xor = 0; + break; + case GXxor: /* 0 1 1 0 */ + and = FB_ALLONES; + xor = fg; + break; + case GXor: /* 0 1 1 1 */ + and = ~fg; + xor = fg; + break; + case GXnor: /* 1 0 0 0 */ + and = ~fg; + xor = ~fg; + break; + case GXequiv: /* 1 0 0 1 */ + and = FB_ALLONES; + xor = ~fg; + break; + case GXinvert: /* 1 0 1 0 */ + and = FB_ALLONES; + xor = FB_ALLONES; + break; + case GXorReverse: /* 1 0 1 1 */ + and = ~fg; + xor = FB_ALLONES; + break; + case GXcopyInverted: /* 1 1 0 0 */ + and = 0; + xor = ~fg; + break; + case GXorInverted: /* 1 1 0 1 */ + and = fg; + xor = ~fg; + break; + case GXnand: /* 1 1 1 0 */ + and = fg; + xor = FB_ALLONES; + break; + case GXset: /* 1 1 1 1 */ + and = 0; + xor = FB_ALLONES; + break; + } + and |= ~pm; + xor &= pm; + *andp = and; + *xorp = xor; +} + +#define O 0 +#define I FB_ALLONES + +const FbMergeRopRec FbMergeRopBits[16] = { + { O,O,O,O }, /* clear 0x0 0 */ + { I,O,O,O }, /* and 0x1 src AND dst */ + { I,O,I,O }, /* andReverse 0x2 src AND NOT dst */ + { O,O,I,O }, /* copy 0x3 src */ + { I,I,O,O }, /* andInverted 0x4 NOT src AND dst */ + { O,I,O,O }, /* noop 0x5 dst */ + { O,I,I,O }, /* xor 0x6 src XOR dst */ + { I,I,I,O }, /* or 0x7 src OR dst */ + { I,I,I,I }, /* nor 0x8 NOT src AND NOT dst */ + { O,I,I,I }, /* equiv 0x9 NOT src XOR dst */ + { O,I,O,I }, /* invert 0xa NOT dst */ + { I,I,O,I }, /* orReverse 0xb src OR NOT dst */ + { O,O,I,I }, /* copyInverted 0xc NOT src */ + { I,O,I,I }, /* orInverted 0xd NOT src OR dst */ + { I,O,O,I }, /* nand 0xe NOT src OR NOT dst */ + { O,O,O,I }, /* set 0xf 1 */ +}; + +/* + * Stipple masks are independent of bit/byte order as long + * as bitorder == byteorder. FB doesn't handle the case + * where these differ + */ +#define BitsMask(x,w) ((FB_ALLONES << ((x) & FB_MASK)) & \ + (FB_ALLONES >> ((FB_UNIT - ((x) + (w))) & FB_MASK))) + +#define Mask(x,w) BitsMask((x)*(w),(w)) + + +#define SelMask(b,n,w) ((((b) >> n) & 1) * Mask(n,w)) + +#define C1(b,w) \ + (SelMask(b,0,w)) + +#define C2(b,w) \ + (SelMask(b,0,w) | \ + SelMask(b,1,w)) + +#define C4(b,w) \ + (SelMask(b,0,w) | \ + SelMask(b,1,w) | \ + SelMask(b,2,w) | \ + SelMask(b,3,w)) + +#define C8(b,w) \ + (SelMask(b,0,w) | \ + SelMask(b,1,w) | \ + SelMask(b,2,w) | \ + SelMask(b,3,w) | \ + SelMask(b,4,w) | \ + SelMask(b,5,w) | \ + SelMask(b,6,w) | \ + SelMask(b,7,w)) + +#if FB_UNIT == 16 +#define fbStipple16Bits 0 +#define fbStipple8Bits 0 +const FbBits fbStipple4Bits[16] = { + C4( 0,4), C4( 1,4), C4( 2,4), C4( 3,4), C4( 4,4), C4( 5,4), + C4( 6,4), C4( 7,4), C4( 8,4), C4( 9,4), C4( 10,4), C4( 11,4), + C4( 12,4), C4( 13,4), C4( 14,4), C4( 15,4),}; +const FbBits fbStipple2Bits[4] = { + C2( 0,8), C2( 1,8), C2( 2,8), C2( 3,8), +}; +const FbBits fbStipple1Bits[2] = { + C1( 0,16), C1( 1,16), +}; +#endif +#if FB_UNIT == 32 +#define fbStipple16Bits 0 +const FbBits fbStipple8Bits[256] = { + C8( 0,4), C8( 1,4), C8( 2,4), C8( 3,4), C8( 4,4), C8( 5,4), + C8( 6,4), C8( 7,4), C8( 8,4), C8( 9,4), C8( 10,4), C8( 11,4), + C8( 12,4), C8( 13,4), C8( 14,4), C8( 15,4), C8( 16,4), C8( 17,4), + C8( 18,4), C8( 19,4), C8( 20,4), C8( 21,4), C8( 22,4), C8( 23,4), + C8( 24,4), C8( 25,4), C8( 26,4), C8( 27,4), C8( 28,4), C8( 29,4), + C8( 30,4), C8( 31,4), C8( 32,4), C8( 33,4), C8( 34,4), C8( 35,4), + C8( 36,4), C8( 37,4), C8( 38,4), C8( 39,4), C8( 40,4), C8( 41,4), + C8( 42,4), C8( 43,4), C8( 44,4), C8( 45,4), C8( 46,4), C8( 47,4), + C8( 48,4), C8( 49,4), C8( 50,4), C8( 51,4), C8( 52,4), C8( 53,4), + C8( 54,4), C8( 55,4), C8( 56,4), C8( 57,4), C8( 58,4), C8( 59,4), + C8( 60,4), C8( 61,4), C8( 62,4), C8( 63,4), C8( 64,4), C8( 65,4), + C8( 66,4), C8( 67,4), C8( 68,4), C8( 69,4), C8( 70,4), C8( 71,4), + C8( 72,4), C8( 73,4), C8( 74,4), C8( 75,4), C8( 76,4), C8( 77,4), + C8( 78,4), C8( 79,4), C8( 80,4), C8( 81,4), C8( 82,4), C8( 83,4), + C8( 84,4), C8( 85,4), C8( 86,4), C8( 87,4), C8( 88,4), C8( 89,4), + C8( 90,4), C8( 91,4), C8( 92,4), C8( 93,4), C8( 94,4), C8( 95,4), + C8( 96,4), C8( 97,4), C8( 98,4), C8( 99,4), C8(100,4), C8(101,4), + C8(102,4), C8(103,4), C8(104,4), C8(105,4), C8(106,4), C8(107,4), + C8(108,4), C8(109,4), C8(110,4), C8(111,4), C8(112,4), C8(113,4), + C8(114,4), C8(115,4), C8(116,4), C8(117,4), C8(118,4), C8(119,4), + C8(120,4), C8(121,4), C8(122,4), C8(123,4), C8(124,4), C8(125,4), + C8(126,4), C8(127,4), C8(128,4), C8(129,4), C8(130,4), C8(131,4), + C8(132,4), C8(133,4), C8(134,4), C8(135,4), C8(136,4), C8(137,4), + C8(138,4), C8(139,4), C8(140,4), C8(141,4), C8(142,4), C8(143,4), + C8(144,4), C8(145,4), C8(146,4), C8(147,4), C8(148,4), C8(149,4), + C8(150,4), C8(151,4), C8(152,4), C8(153,4), C8(154,4), C8(155,4), + C8(156,4), C8(157,4), C8(158,4), C8(159,4), C8(160,4), C8(161,4), + C8(162,4), C8(163,4), C8(164,4), C8(165,4), C8(166,4), C8(167,4), + C8(168,4), C8(169,4), C8(170,4), C8(171,4), C8(172,4), C8(173,4), + C8(174,4), C8(175,4), C8(176,4), C8(177,4), C8(178,4), C8(179,4), + C8(180,4), C8(181,4), C8(182,4), C8(183,4), C8(184,4), C8(185,4), + C8(186,4), C8(187,4), C8(188,4), C8(189,4), C8(190,4), C8(191,4), + C8(192,4), C8(193,4), C8(194,4), C8(195,4), C8(196,4), C8(197,4), + C8(198,4), C8(199,4), C8(200,4), C8(201,4), C8(202,4), C8(203,4), + C8(204,4), C8(205,4), C8(206,4), C8(207,4), C8(208,4), C8(209,4), + C8(210,4), C8(211,4), C8(212,4), C8(213,4), C8(214,4), C8(215,4), + C8(216,4), C8(217,4), C8(218,4), C8(219,4), C8(220,4), C8(221,4), + C8(222,4), C8(223,4), C8(224,4), C8(225,4), C8(226,4), C8(227,4), + C8(228,4), C8(229,4), C8(230,4), C8(231,4), C8(232,4), C8(233,4), + C8(234,4), C8(235,4), C8(236,4), C8(237,4), C8(238,4), C8(239,4), + C8(240,4), C8(241,4), C8(242,4), C8(243,4), C8(244,4), C8(245,4), + C8(246,4), C8(247,4), C8(248,4), C8(249,4), C8(250,4), C8(251,4), + C8(252,4), C8(253,4), C8(254,4), C8(255,4), +}; +const FbBits fbStipple4Bits[16] = { + C4( 0,8), C4( 1,8), C4( 2,8), C4( 3,8), C4( 4,8), C4( 5,8), + C4( 6,8), C4( 7,8), C4( 8,8), C4( 9,8), C4( 10,8), C4( 11,8), + C4( 12,8), C4( 13,8), C4( 14,8), C4( 15,8),}; +const FbBits fbStipple2Bits[4] = { + C2( 0,16), C2( 1,16), C2( 2,16), C2( 3,16), +}; +const FbBits fbStipple1Bits[2] = { + C1( 0,32), C1( 1,32), +}; +#endif +#if FB_UNIT == 64 +const FbBits fbStipple16Bits[256] = { + C8( 0,4), C8( 1,4), C8( 2,4), C8( 3,4), C8( 4,4), C8( 5,4), + C8( 6,4), C8( 7,4), C8( 8,4), C8( 9,4), C8( 10,4), C8( 11,4), + C8( 12,4), C8( 13,4), C8( 14,4), C8( 15,4), C8( 16,4), C8( 17,4), + C8( 18,4), C8( 19,4), C8( 20,4), C8( 21,4), C8( 22,4), C8( 23,4), + C8( 24,4), C8( 25,4), C8( 26,4), C8( 27,4), C8( 28,4), C8( 29,4), + C8( 30,4), C8( 31,4), C8( 32,4), C8( 33,4), C8( 34,4), C8( 35,4), + C8( 36,4), C8( 37,4), C8( 38,4), C8( 39,4), C8( 40,4), C8( 41,4), + C8( 42,4), C8( 43,4), C8( 44,4), C8( 45,4), C8( 46,4), C8( 47,4), + C8( 48,4), C8( 49,4), C8( 50,4), C8( 51,4), C8( 52,4), C8( 53,4), + C8( 54,4), C8( 55,4), C8( 56,4), C8( 57,4), C8( 58,4), C8( 59,4), + C8( 60,4), C8( 61,4), C8( 62,4), C8( 63,4), C8( 64,4), C8( 65,4), + C8( 66,4), C8( 67,4), C8( 68,4), C8( 69,4), C8( 70,4), C8( 71,4), + C8( 72,4), C8( 73,4), C8( 74,4), C8( 75,4), C8( 76,4), C8( 77,4), + C8( 78,4), C8( 79,4), C8( 80,4), C8( 81,4), C8( 82,4), C8( 83,4), + C8( 84,4), C8( 85,4), C8( 86,4), C8( 87,4), C8( 88,4), C8( 89,4), + C8( 90,4), C8( 91,4), C8( 92,4), C8( 93,4), C8( 94,4), C8( 95,4), + C8( 96,4), C8( 97,4), C8( 98,4), C8( 99,4), C8(100,4), C8(101,4), + C8(102,4), C8(103,4), C8(104,4), C8(105,4), C8(106,4), C8(107,4), + C8(108,4), C8(109,4), C8(110,4), C8(111,4), C8(112,4), C8(113,4), + C8(114,4), C8(115,4), C8(116,4), C8(117,4), C8(118,4), C8(119,4), + C8(120,4), C8(121,4), C8(122,4), C8(123,4), C8(124,4), C8(125,4), + C8(126,4), C8(127,4), C8(128,4), C8(129,4), C8(130,4), C8(131,4), + C8(132,4), C8(133,4), C8(134,4), C8(135,4), C8(136,4), C8(137,4), + C8(138,4), C8(139,4), C8(140,4), C8(141,4), C8(142,4), C8(143,4), + C8(144,4), C8(145,4), C8(146,4), C8(147,4), C8(148,4), C8(149,4), + C8(150,4), C8(151,4), C8(152,4), C8(153,4), C8(154,4), C8(155,4), + C8(156,4), C8(157,4), C8(158,4), C8(159,4), C8(160,4), C8(161,4), + C8(162,4), C8(163,4), C8(164,4), C8(165,4), C8(166,4), C8(167,4), + C8(168,4), C8(169,4), C8(170,4), C8(171,4), C8(172,4), C8(173,4), + C8(174,4), C8(175,4), C8(176,4), C8(177,4), C8(178,4), C8(179,4), + C8(180,4), C8(181,4), C8(182,4), C8(183,4), C8(184,4), C8(185,4), + C8(186,4), C8(187,4), C8(188,4), C8(189,4), C8(190,4), C8(191,4), + C8(192,4), C8(193,4), C8(194,4), C8(195,4), C8(196,4), C8(197,4), + C8(198,4), C8(199,4), C8(200,4), C8(201,4), C8(202,4), C8(203,4), + C8(204,4), C8(205,4), C8(206,4), C8(207,4), C8(208,4), C8(209,4), + C8(210,4), C8(211,4), C8(212,4), C8(213,4), C8(214,4), C8(215,4), + C8(216,4), C8(217,4), C8(218,4), C8(219,4), C8(220,4), C8(221,4), + C8(222,4), C8(223,4), C8(224,4), C8(225,4), C8(226,4), C8(227,4), + C8(228,4), C8(229,4), C8(230,4), C8(231,4), C8(232,4), C8(233,4), + C8(234,4), C8(235,4), C8(236,4), C8(237,4), C8(238,4), C8(239,4), + C8(240,4), C8(241,4), C8(242,4), C8(243,4), C8(244,4), C8(245,4), + C8(246,4), C8(247,4), C8(248,4), C8(249,4), C8(250,4), C8(251,4), + C8(252,4), C8(253,4), C8(254,4), C8(255,4), +}; +const FbBits fbStipple8Bits[256] = { + C8( 0,8), C8( 1,8), C8( 2,8), C8( 3,8), C8( 4,8), C8( 5,8), + C8( 6,8), C8( 7,8), C8( 8,8), C8( 9,8), C8( 10,8), C8( 11,8), + C8( 12,8), C8( 13,8), C8( 14,8), C8( 15,8), C8( 16,8), C8( 17,8), + C8( 18,8), C8( 19,8), C8( 20,8), C8( 21,8), C8( 22,8), C8( 23,8), + C8( 24,8), C8( 25,8), C8( 26,8), C8( 27,8), C8( 28,8), C8( 29,8), + C8( 30,8), C8( 31,8), C8( 32,8), C8( 33,8), C8( 34,8), C8( 35,8), + C8( 36,8), C8( 37,8), C8( 38,8), C8( 39,8), C8( 40,8), C8( 41,8), + C8( 42,8), C8( 43,8), C8( 44,8), C8( 45,8), C8( 46,8), C8( 47,8), + C8( 48,8), C8( 49,8), C8( 50,8), C8( 51,8), C8( 52,8), C8( 53,8), + C8( 54,8), C8( 55,8), C8( 56,8), C8( 57,8), C8( 58,8), C8( 59,8), + C8( 60,8), C8( 61,8), C8( 62,8), C8( 63,8), C8( 64,8), C8( 65,8), + C8( 66,8), C8( 67,8), C8( 68,8), C8( 69,8), C8( 70,8), C8( 71,8), + C8( 72,8), C8( 73,8), C8( 74,8), C8( 75,8), C8( 76,8), C8( 77,8), + C8( 78,8), C8( 79,8), C8( 80,8), C8( 81,8), C8( 82,8), C8( 83,8), + C8( 84,8), C8( 85,8), C8( 86,8), C8( 87,8), C8( 88,8), C8( 89,8), + C8( 90,8), C8( 91,8), C8( 92,8), C8( 93,8), C8( 94,8), C8( 95,8), + C8( 96,8), C8( 97,8), C8( 98,8), C8( 99,8), C8(100,8), C8(101,8), + C8(102,8), C8(103,8), C8(104,8), C8(105,8), C8(106,8), C8(107,8), + C8(108,8), C8(109,8), C8(110,8), C8(111,8), C8(112,8), C8(113,8), + C8(114,8), C8(115,8), C8(116,8), C8(117,8), C8(118,8), C8(119,8), + C8(120,8), C8(121,8), C8(122,8), C8(123,8), C8(124,8), C8(125,8), + C8(126,8), C8(127,8), C8(128,8), C8(129,8), C8(130,8), C8(131,8), + C8(132,8), C8(133,8), C8(134,8), C8(135,8), C8(136,8), C8(137,8), + C8(138,8), C8(139,8), C8(140,8), C8(141,8), C8(142,8), C8(143,8), + C8(144,8), C8(145,8), C8(146,8), C8(147,8), C8(148,8), C8(149,8), + C8(150,8), C8(151,8), C8(152,8), C8(153,8), C8(154,8), C8(155,8), + C8(156,8), C8(157,8), C8(158,8), C8(159,8), C8(160,8), C8(161,8), + C8(162,8), C8(163,8), C8(164,8), C8(165,8), C8(166,8), C8(167,8), + C8(168,8), C8(169,8), C8(170,8), C8(171,8), C8(172,8), C8(173,8), + C8(174,8), C8(175,8), C8(176,8), C8(177,8), C8(178,8), C8(179,8), + C8(180,8), C8(181,8), C8(182,8), C8(183,8), C8(184,8), C8(185,8), + C8(186,8), C8(187,8), C8(188,8), C8(189,8), C8(190,8), C8(191,8), + C8(192,8), C8(193,8), C8(194,8), C8(195,8), C8(196,8), C8(197,8), + C8(198,8), C8(199,8), C8(200,8), C8(201,8), C8(202,8), C8(203,8), + C8(204,8), C8(205,8), C8(206,8), C8(207,8), C8(208,8), C8(209,8), + C8(210,8), C8(211,8), C8(212,8), C8(213,8), C8(214,8), C8(215,8), + C8(216,8), C8(217,8), C8(218,8), C8(219,8), C8(220,8), C8(221,8), + C8(222,8), C8(223,8), C8(224,8), C8(225,8), C8(226,8), C8(227,8), + C8(228,8), C8(229,8), C8(230,8), C8(231,8), C8(232,8), C8(233,8), + C8(234,8), C8(235,8), C8(236,8), C8(237,8), C8(238,8), C8(239,8), + C8(240,8), C8(241,8), C8(242,8), C8(243,8), C8(244,8), C8(245,8), + C8(246,8), C8(247,8), C8(248,8), C8(249,8), C8(250,8), C8(251,8), + C8(252,8), C8(253,8), C8(254,8), C8(255,8), +}; +const FbBits fbStipple4Bits[16] = { + C4( 0,16), C4( 1,16), C4( 2,16), C4( 3,16), C4( 4,16), C4( 5,16), + C4( 6,16), C4( 7,16), C4( 8,16), C4( 9,16), C4( 10,16), C4( 11,16), + C4( 12,16), C4( 13,16), C4( 14,16), C4( 15,16),}; +const FbBits fbStipple2Bits[4] = { + C2( 0,32), C2( 1,32), C2( 2,32), C2( 3,32), +}; +#define fbStipple1Bits 0 +#endif +const FbBits * const fbStippleTable[] = { + 0, + fbStipple1Bits, + fbStipple2Bits, + 0, + fbStipple4Bits, + 0, + 0, + 0, + fbStipple8Bits, +}; diff --git a/fb/fbwindow.c b/fb/fbwindow.c new file mode 100644 index 000000000..36952614f --- /dev/null +++ b/fb/fbwindow.c @@ -0,0 +1,341 @@ +/* + * Id: fbwindow.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. + */ +/* $XFree86: xc/programs/Xserver/fb/fbwindow.c,v 1.10 2003/01/31 00:01:45 torrey Exp $ */ + +#include "fb.h" +#ifdef IN_MODULE +#include "xf86_ansic.h" +#endif + +Bool +fbCreateWindow(WindowPtr pWin) +{ +#ifndef FB_NO_WINDOW_PIXMAPS + pWin->devPrivates[fbWinPrivateIndex].ptr = + (pointer) fbGetScreenPixmap(pWin->drawable.pScreen); +#endif +#ifdef FB_SCREEN_PRIVATE + if (pWin->drawable.bitsPerPixel == 32) + pWin->drawable.bitsPerPixel = fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp; +#endif + return TRUE; +} + +Bool +fbDestroyWindow(WindowPtr pWin) +{ + return TRUE; +} + +Bool +fbMapWindow(WindowPtr pWindow) +{ + return TRUE; +} + +Bool +fbPositionWindow(WindowPtr pWin, int x, int y) +{ + return TRUE; +} + +Bool +fbUnmapWindow(WindowPtr pWindow) +{ + return TRUE; +} + +void +fbCopyWindowProc (DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GCPtr pGC, + BoxPtr pbox, + int nbox, + int dx, + int dy, + Bool reverse, + Bool upsidedown, + Pixel bitplane, + void *closure) +{ + FbBits *src; + FbStride srcStride; + int srcBpp; + int srcXoff, srcYoff; + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + + fbGetDrawable (pSrcDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); + fbGetDrawable (pDstDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + while (nbox--) + { + fbBlt (src + (pbox->y1 + dy + srcYoff) * srcStride, + srcStride, + (pbox->x1 + dx + srcXoff) * srcBpp, + + dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + + (pbox->x2 - pbox->x1) * dstBpp, + (pbox->y2 - pbox->y1), + + GXcopy, + FB_ALLONES, + dstBpp, + + reverse, + upsidedown); + pbox++; + } +} + +void +fbCopyWindow(WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + 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, fbCopyWindowProc, 0, 0); + + REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); + fbValidateDrawable (&pWin->drawable); +} + +Bool +fbChangeWindowAttributes(WindowPtr pWin, unsigned long mask) +{ + PixmapPtr pPixmap; + + if (mask & CWBackPixmap) + { + if (pWin->backgroundState == BackgroundPixmap) + { + pPixmap = pWin->background.pixmap; +#ifdef FB_24_32BIT + if (pPixmap->drawable.bitsPerPixel != pWin->drawable.bitsPerPixel) + { + pPixmap = fb24_32ReformatTile (pPixmap, + pWin->drawable.bitsPerPixel); + if (pPixmap) + { + (*pWin->drawable.pScreen->DestroyPixmap) (pWin->background.pixmap); + pWin->background.pixmap = pPixmap; + } + } +#endif + if (FbEvenTile (pPixmap->drawable.width * + pPixmap->drawable.bitsPerPixel)) + fbPadPixmap (pPixmap); + } + } + if (mask & CWBorderPixmap) + { + if (pWin->borderIsPixel == FALSE) + { + pPixmap = pWin->border.pixmap; +#ifdef FB_24_32BIT + if (pPixmap->drawable.bitsPerPixel != + pWin->drawable.bitsPerPixel) + { + pPixmap = fb24_32ReformatTile (pPixmap, + pWin->drawable.bitsPerPixel); + if (pPixmap) + { + (*pWin->drawable.pScreen->DestroyPixmap) (pWin->border.pixmap); + pWin->border.pixmap = pPixmap; + } + } +#endif + if (FbEvenTile (pPixmap->drawable.width * + pPixmap->drawable.bitsPerPixel)) + fbPadPixmap (pPixmap); + } + } + return TRUE; +} + +void +fbFillRegionSolid (DrawablePtr pDrawable, + RegionPtr pRegion, + FbBits and, + FbBits xor) +{ + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + int n = REGION_NUM_RECTS(pRegion); + BoxPtr pbox = REGION_RECTS(pRegion); + + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + + while (n--) + { + fbSolid (dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + dstBpp, + (pbox->x2 - pbox->x1) * dstBpp, + pbox->y2 - pbox->y1, + and, xor); + fbValidateDrawable (pDrawable); + pbox++; + } +} + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +void +fbFillRegionTiled (DrawablePtr pDrawable, + RegionPtr pRegion, + PixmapPtr pTile) +{ + FbBits *dst; + FbStride dstStride; + int dstBpp; + int dstXoff, dstYoff; + FbBits *tile; + FbStride tileStride; + int tileBpp; + int tileXoff, tileYoff; /* XXX assumed to be zero */ + int tileWidth, tileHeight; + int n = REGION_NUM_RECTS(pRegion); + BoxPtr pbox = REGION_RECTS(pRegion); + int xRot = pDrawable->x; + int yRot = pDrawable->y; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + { + int index = pDrawable->pScreen->myNum; + if(&WindowTable[index]->drawable == pDrawable) + { + xRot -= panoramiXdataPtr[index].x; + yRot -= panoramiXdataPtr[index].y; + } + } +#endif + fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); + fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp, tileXoff, tileYoff); + tileWidth = pTile->drawable.width; + tileHeight = pTile->drawable.height; + xRot += dstXoff; + yRot += dstYoff; + + while (n--) + { + fbTile (dst + (pbox->y1 + dstYoff) * dstStride, + dstStride, + (pbox->x1 + dstXoff) * dstBpp, + (pbox->x2 - pbox->x1) * dstBpp, + pbox->y2 - pbox->y1, + tile, + tileStride, + tileWidth * dstBpp, + tileHeight, + GXcopy, + FB_ALLONES, + dstBpp, + xRot * dstBpp, + yRot - pbox->y1); + pbox++; + } +} + +void +fbPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) +{ + WindowPtr pBgWin; + + switch (what) { + case PW_BACKGROUND: + switch (pWin->backgroundState) { + case None: + break; + case ParentRelative: + do { + pWin = pWin->parent; + } while (pWin->backgroundState == ParentRelative); + (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, + what); + break; + case BackgroundPixmap: + fbFillRegionTiled (&pWin->drawable, + pRegion, + pWin->background.pixmap); + break; + case BackgroundPixel: + fbFillRegionSolid (&pWin->drawable, + pRegion, + 0, + fbReplicatePixel (pWin->background.pixel, + pWin->drawable.bitsPerPixel)); + break; + } + break; + case PW_BORDER: + if (pWin->borderIsPixel) + { + fbFillRegionSolid (&pWin->drawable, + pRegion, + 0, + fbReplicatePixel (pWin->border.pixel, + pWin->drawable.bitsPerPixel)); + } + else + { + for (pBgWin = pWin; + pBgWin->backgroundState == ParentRelative; + pBgWin = pBgWin->parent); + + fbFillRegionTiled (&pBgWin->drawable, + pRegion, + pWin->border.pixmap); + } + break; + } + fbValidateDrawable (&pWin->drawable); +} |