fbbltone.c revision 9ace9065
105b261ecSmrg/* 205b261ecSmrg * Copyright © 1998 Keith Packard 305b261ecSmrg * 405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 605b261ecSmrg * the above copyright notice appear in all copies and that both that 705b261ecSmrg * copyright notice and this permission notice appear in supporting 805b261ecSmrg * documentation, and that the name of Keith Packard not be used in 905b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1005b261ecSmrg * specific, written prior permission. Keith Packard makes no 1105b261ecSmrg * representations about the suitability of this software for any purpose. It 1205b261ecSmrg * is provided "as is" without express or implied warranty. 1305b261ecSmrg * 1405b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1605b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2105b261ecSmrg */ 2205b261ecSmrg 2305b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2405b261ecSmrg#include <dix-config.h> 2505b261ecSmrg#endif 2605b261ecSmrg 2705b261ecSmrg#include "fb.h" 2805b261ecSmrg 2905b261ecSmrg/* 3005b261ecSmrg * Example: srcX = 13 dstX = 8 (FB unit 32 dstBpp 8) 3105b261ecSmrg * 3205b261ecSmrg * **** **** **** **** **** **** **** **** 3305b261ecSmrg * ^ 3405b261ecSmrg * ******** ******** ******** ******** 3505b261ecSmrg * ^ 3605b261ecSmrg * leftShift = 12 3705b261ecSmrg * rightShift = 20 3805b261ecSmrg * 3905b261ecSmrg * Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8) 4005b261ecSmrg * 4105b261ecSmrg * **** **** **** **** **** **** **** **** 4205b261ecSmrg * ^ 4305b261ecSmrg * ******** ******** ******** ******** 4405b261ecSmrg * ^ 4505b261ecSmrg * 4605b261ecSmrg * leftShift = 24 4705b261ecSmrg * rightShift = 8 4805b261ecSmrg */ 4905b261ecSmrg 5005b261ecSmrg#define LoadBits {\ 5105b261ecSmrg if (leftShift) { \ 5205b261ecSmrg bitsRight = (src < srcEnd ? READ(src++) : 0); \ 5305b261ecSmrg bits = (FbStipLeft (bitsLeft, leftShift) | \ 5405b261ecSmrg FbStipRight(bitsRight, rightShift)); \ 5505b261ecSmrg bitsLeft = bitsRight; \ 5605b261ecSmrg } else \ 5705b261ecSmrg bits = (src < srcEnd ? READ(src++) : 0); \ 5805b261ecSmrg} 5905b261ecSmrg 6005b261ecSmrg#ifndef FBNOPIXADDR 6105b261ecSmrg 626747b715Smrg#define LaneCases1(n,a) case n: FbLaneCase(n,a); break 6305b261ecSmrg#define LaneCases2(n,a) LaneCases1(n,a); LaneCases1(n+1,a) 6405b261ecSmrg#define LaneCases4(n,a) LaneCases2(n,a); LaneCases2(n+2,a) 6505b261ecSmrg#define LaneCases8(n,a) LaneCases4(n,a); LaneCases4(n+4,a) 6605b261ecSmrg#define LaneCases16(n,a) LaneCases8(n,a); LaneCases8(n+8,a) 6705b261ecSmrg#define LaneCases32(n,a) LaneCases16(n,a); LaneCases16(n+16,a) 6805b261ecSmrg#define LaneCases64(n,a) LaneCases32(n,a); LaneCases32(n+32,a) 6905b261ecSmrg#define LaneCases128(n,a) LaneCases64(n,a); LaneCases64(n+64,a) 7005b261ecSmrg#define LaneCases256(n,a) LaneCases128(n,a); LaneCases128(n+128,a) 7105b261ecSmrg 7205b261ecSmrg#if FB_SHIFT == 6 7305b261ecSmrg#define LaneCases(a) LaneCases256(0,a) 7405b261ecSmrg#endif 7505b261ecSmrg 7605b261ecSmrg#if FB_SHIFT == 5 7705b261ecSmrg#define LaneCases(a) LaneCases16(0,a) 7805b261ecSmrg#endif 7905b261ecSmrg 8005b261ecSmrg#if FB_SHIFT == 6 8105b261ecSmrgCARD8 fb8Lane[256] = { 8205b261ecSmrg0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 8305b261ecSmrg22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 8405b261ecSmrg41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 8505b261ecSmrg60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 8605b261ecSmrg79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 8705b261ecSmrg98, 99, 100, 101, 102,103,104,105,106,107,108,109,110,111,112,113,114,115, 8805b261ecSmrg116, 117, 118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133, 8905b261ecSmrg134, 135, 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151, 9005b261ecSmrg152, 153, 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169, 9105b261ecSmrg170, 171, 172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187, 9205b261ecSmrg188, 189, 190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205, 9305b261ecSmrg206, 207, 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 9405b261ecSmrg224, 225, 226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241, 9505b261ecSmrg242, 243, 244,245,246,247,248,249,250,251,252,253,254,255, 9605b261ecSmrg}; 9705b261ecSmrg 9805b261ecSmrgCARD8 fb16Lane[256] = { 9905b261ecSmrg 0x00, 0x03, 0x0c, 0x0f, 10005b261ecSmrg 0x30, 0x33, 0x3c, 0x3f, 10105b261ecSmrg 0xc0, 0xc3, 0xcc, 0xcf, 10205b261ecSmrg 0xf0, 0xf3, 0xfc, 0xff, 10305b261ecSmrg}; 10405b261ecSmrg 10505b261ecSmrgCARD8 fb32Lane[16] = { 10605b261ecSmrg 0x00, 0x0f, 0xf0, 0xff, 10705b261ecSmrg}; 10805b261ecSmrg#endif 10905b261ecSmrg 11005b261ecSmrg#if FB_SHIFT == 5 11105b261ecSmrgCARD8 fb8Lane[16] = { 11205b261ecSmrg 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 11305b261ecSmrg}; 11405b261ecSmrg 11505b261ecSmrgCARD8 fb16Lane[16] = { 11605b261ecSmrg 0, 3, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11705b261ecSmrg}; 11805b261ecSmrg 11905b261ecSmrgCARD8 fb32Lane[16] = { 12005b261ecSmrg 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12105b261ecSmrg}; 12205b261ecSmrg#endif 12305b261ecSmrg 12405b261ecSmrgCARD8 *fbLaneTable[33] = { 12505b261ecSmrg 0, 0, 0, 0, 0, 0, 0, 0, 12605b261ecSmrg fb8Lane, 0, 0, 0, 0, 0, 0, 0, 12705b261ecSmrg fb16Lane, 0, 0, 0, 0, 0, 0, 0, 12805b261ecSmrg 0, 0, 0, 0, 0, 0, 0, 0, 12905b261ecSmrg fb32Lane 13005b261ecSmrg}; 13105b261ecSmrg#endif 13205b261ecSmrg 13305b261ecSmrgvoid 13405b261ecSmrgfbBltOne (FbStip *src, 13505b261ecSmrg FbStride srcStride, /* FbStip units per scanline */ 13605b261ecSmrg int srcX, /* bit position of source */ 13705b261ecSmrg FbBits *dst, 13805b261ecSmrg FbStride dstStride, /* FbBits units per scanline */ 13905b261ecSmrg int dstX, /* bit position of dest */ 14005b261ecSmrg int dstBpp, /* bits per destination unit */ 14105b261ecSmrg 14205b261ecSmrg int width, /* width in bits of destination */ 14305b261ecSmrg int height, /* height in scanlines */ 14405b261ecSmrg 14505b261ecSmrg FbBits fgand, /* rrop values */ 14605b261ecSmrg FbBits fgxor, 14705b261ecSmrg FbBits bgand, 14805b261ecSmrg FbBits bgxor) 14905b261ecSmrg{ 15005b261ecSmrg const FbBits *fbBits; 15105b261ecSmrg FbBits *srcEnd; 15205b261ecSmrg int pixelsPerDst; /* dst pixels per FbBits */ 15305b261ecSmrg int unitsPerSrc; /* src patterns per FbStip */ 15405b261ecSmrg int leftShift, rightShift; /* align source with dest */ 15505b261ecSmrg FbBits startmask, endmask; /* dest scanline masks */ 15605b261ecSmrg FbStip bits=0, bitsLeft, bitsRight;/* source bits */ 15705b261ecSmrg FbStip left; 15805b261ecSmrg FbBits mask; 15905b261ecSmrg int nDst; /* dest longwords (w.o. end) */ 16005b261ecSmrg int w; 16105b261ecSmrg int n, nmiddle; 16205b261ecSmrg int dstS; /* stipple-relative dst X coordinate */ 16305b261ecSmrg Bool copy; /* accelerate dest-invariant */ 16405b261ecSmrg Bool transparent; /* accelerate 0 nop */ 16505b261ecSmrg int srcinc; /* source units consumed */ 16605b261ecSmrg Bool endNeedsLoad = FALSE; /* need load for endmask */ 16705b261ecSmrg#ifndef FBNOPIXADDR 16805b261ecSmrg CARD8 *fbLane; 16905b261ecSmrg#endif 17005b261ecSmrg int startbyte, endbyte; 17105b261ecSmrg 17205b261ecSmrg#ifdef FB_24BIT 17305b261ecSmrg if (dstBpp == 24) 17405b261ecSmrg { 17505b261ecSmrg fbBltOne24 (src, srcStride, srcX, 17605b261ecSmrg dst, dstStride, dstX, dstBpp, 17705b261ecSmrg width, height, 17805b261ecSmrg fgand, fgxor, bgand, bgxor); 17905b261ecSmrg return; 18005b261ecSmrg } 18105b261ecSmrg#endif 18205b261ecSmrg 18305b261ecSmrg /* 18405b261ecSmrg * Do not read past the end of the buffer! 18505b261ecSmrg */ 18605b261ecSmrg srcEnd = src + height * srcStride; 18705b261ecSmrg 18805b261ecSmrg /* 18905b261ecSmrg * Number of destination units in FbBits == number of stipple pixels 19005b261ecSmrg * used each time 19105b261ecSmrg */ 19205b261ecSmrg pixelsPerDst = FB_UNIT / dstBpp; 19305b261ecSmrg 19405b261ecSmrg /* 19505b261ecSmrg * Number of source stipple patterns in FbStip 19605b261ecSmrg */ 19705b261ecSmrg unitsPerSrc = FB_STIP_UNIT / pixelsPerDst; 19805b261ecSmrg 19905b261ecSmrg copy = FALSE; 20005b261ecSmrg transparent = FALSE; 20105b261ecSmrg if (bgand == 0 && fgand == 0) 20205b261ecSmrg copy = TRUE; 20305b261ecSmrg else if (bgand == FB_ALLONES && bgxor == 0) 20405b261ecSmrg transparent = TRUE; 20505b261ecSmrg 20605b261ecSmrg /* 20705b261ecSmrg * Adjust source and dest to nearest FbBits boundary 20805b261ecSmrg */ 20905b261ecSmrg src += srcX >> FB_STIP_SHIFT; 21005b261ecSmrg dst += dstX >> FB_SHIFT; 21105b261ecSmrg srcX &= FB_STIP_MASK; 21205b261ecSmrg dstX &= FB_MASK; 21305b261ecSmrg 21405b261ecSmrg FbMaskBitsBytes(dstX, width, copy, 21505b261ecSmrg startmask, startbyte, nmiddle, endmask, endbyte); 21605b261ecSmrg 21705b261ecSmrg /* 21805b261ecSmrg * Compute effective dest alignment requirement for 21905b261ecSmrg * source -- must align source to dest unit boundary 22005b261ecSmrg */ 22105b261ecSmrg dstS = dstX / dstBpp; 22205b261ecSmrg /* 22305b261ecSmrg * Compute shift constants for effective alignement 22405b261ecSmrg */ 22505b261ecSmrg if (srcX >= dstS) 22605b261ecSmrg { 22705b261ecSmrg leftShift = srcX - dstS; 22805b261ecSmrg rightShift = FB_STIP_UNIT - leftShift; 22905b261ecSmrg } 23005b261ecSmrg else 23105b261ecSmrg { 23205b261ecSmrg rightShift = dstS - srcX; 23305b261ecSmrg leftShift = FB_STIP_UNIT - rightShift; 23405b261ecSmrg } 23505b261ecSmrg /* 23605b261ecSmrg * Get pointer to stipple mask array for this depth 23705b261ecSmrg */ 23805b261ecSmrg fbBits = 0; /* unused */ 23905b261ecSmrg if (pixelsPerDst <= 8) 24005b261ecSmrg fbBits = fbStippleTable[pixelsPerDst]; 24105b261ecSmrg#ifndef FBNOPIXADDR 24205b261ecSmrg fbLane = 0; 24305b261ecSmrg if (transparent && fgand == 0 && dstBpp >= 8) 24405b261ecSmrg fbLane = fbLaneTable[dstBpp]; 24505b261ecSmrg#endif 24605b261ecSmrg 24705b261ecSmrg /* 24805b261ecSmrg * Compute total number of destination words written, but 24905b261ecSmrg * don't count endmask 25005b261ecSmrg */ 25105b261ecSmrg nDst = nmiddle; 25205b261ecSmrg if (startmask) 25305b261ecSmrg nDst++; 25405b261ecSmrg 25505b261ecSmrg dstStride -= nDst; 25605b261ecSmrg 25705b261ecSmrg /* 25805b261ecSmrg * Compute total number of source words consumed 25905b261ecSmrg */ 26005b261ecSmrg 26105b261ecSmrg srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc; 26205b261ecSmrg 26305b261ecSmrg if (srcX > dstS) 26405b261ecSmrg srcinc++; 26505b261ecSmrg if (endmask) 26605b261ecSmrg { 26705b261ecSmrg endNeedsLoad = nDst % unitsPerSrc == 0; 26805b261ecSmrg if (endNeedsLoad) 26905b261ecSmrg srcinc++; 27005b261ecSmrg } 27105b261ecSmrg 27205b261ecSmrg srcStride -= srcinc; 27305b261ecSmrg 27405b261ecSmrg /* 27505b261ecSmrg * Copy rectangle 27605b261ecSmrg */ 27705b261ecSmrg while (height--) 27805b261ecSmrg { 27905b261ecSmrg w = nDst; /* total units across scanline */ 28005b261ecSmrg n = unitsPerSrc; /* units avail in single stipple */ 28105b261ecSmrg if (n > w) 28205b261ecSmrg n = w; 28305b261ecSmrg 28405b261ecSmrg bitsLeft = 0; 28505b261ecSmrg if (srcX > dstS) 28605b261ecSmrg bitsLeft = READ(src++); 28705b261ecSmrg if (n) 28805b261ecSmrg { 28905b261ecSmrg /* 29005b261ecSmrg * Load first set of stipple bits 29105b261ecSmrg */ 29205b261ecSmrg LoadBits; 29305b261ecSmrg 29405b261ecSmrg /* 29505b261ecSmrg * Consume stipple bits for startmask 29605b261ecSmrg */ 29705b261ecSmrg if (startmask) 29805b261ecSmrg { 29905b261ecSmrg#if FB_UNIT > 32 30005b261ecSmrg if (pixelsPerDst == 16) 30105b261ecSmrg mask = FbStipple16Bits(FbLeftStipBits(bits,16)); 30205b261ecSmrg else 30305b261ecSmrg#endif 30405b261ecSmrg mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; 30505b261ecSmrg#ifndef FBNOPIXADDR 30605b261ecSmrg if (fbLane) 30705b261ecSmrg { 30805b261ecSmrg fbTransparentSpan (dst, mask & startmask, fgxor, 1); 30905b261ecSmrg } 31005b261ecSmrg else 31105b261ecSmrg#endif 31205b261ecSmrg { 31305b261ecSmrg if (mask || !transparent) 31405b261ecSmrg FbDoLeftMaskByteStippleRRop (dst, mask, 31505b261ecSmrg fgand, fgxor, bgand, bgxor, 31605b261ecSmrg startbyte, startmask); 31705b261ecSmrg } 31805b261ecSmrg bits = FbStipLeft (bits, pixelsPerDst); 31905b261ecSmrg dst++; 32005b261ecSmrg n--; 32105b261ecSmrg w--; 32205b261ecSmrg } 32305b261ecSmrg /* 32405b261ecSmrg * Consume stipple bits across scanline 32505b261ecSmrg */ 32605b261ecSmrg for (;;) 32705b261ecSmrg { 32805b261ecSmrg w -= n; 32905b261ecSmrg if (copy) 33005b261ecSmrg { 33105b261ecSmrg while (n--) 33205b261ecSmrg { 33305b261ecSmrg#if FB_UNIT > 32 33405b261ecSmrg if (pixelsPerDst == 16) 33505b261ecSmrg mask = FbStipple16Bits(FbLeftStipBits(bits,16)); 33605b261ecSmrg else 33705b261ecSmrg#endif 33805b261ecSmrg mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; 33905b261ecSmrg WRITE(dst, FbOpaqueStipple (mask, fgxor, bgxor)); 34005b261ecSmrg dst++; 34105b261ecSmrg bits = FbStipLeft(bits, pixelsPerDst); 34205b261ecSmrg } 34305b261ecSmrg } 34405b261ecSmrg else 34505b261ecSmrg { 34605b261ecSmrg#ifndef FBNOPIXADDR 34705b261ecSmrg if (fbLane) 34805b261ecSmrg { 34905b261ecSmrg while (bits && n) 35005b261ecSmrg { 35105b261ecSmrg switch (fbLane[FbLeftStipBits(bits,pixelsPerDst)]) { 35205b261ecSmrg LaneCases((CARD8 *) dst); 35305b261ecSmrg } 35405b261ecSmrg bits = FbStipLeft(bits,pixelsPerDst); 35505b261ecSmrg dst++; 35605b261ecSmrg n--; 35705b261ecSmrg } 35805b261ecSmrg dst += n; 35905b261ecSmrg } 36005b261ecSmrg else 36105b261ecSmrg#endif 36205b261ecSmrg { 36305b261ecSmrg while (n--) 36405b261ecSmrg { 36505b261ecSmrg left = FbLeftStipBits(bits,pixelsPerDst); 36605b261ecSmrg if (left || !transparent) 36705b261ecSmrg { 36805b261ecSmrg mask = fbBits[left]; 36905b261ecSmrg WRITE(dst, FbStippleRRop (READ(dst), mask, 37005b261ecSmrg fgand, fgxor, bgand, bgxor)); 37105b261ecSmrg } 37205b261ecSmrg dst++; 37305b261ecSmrg bits = FbStipLeft(bits, pixelsPerDst); 37405b261ecSmrg } 37505b261ecSmrg } 37605b261ecSmrg } 37705b261ecSmrg if (!w) 37805b261ecSmrg break; 37905b261ecSmrg /* 38005b261ecSmrg * Load another set and reset number of available units 38105b261ecSmrg */ 38205b261ecSmrg LoadBits; 38305b261ecSmrg n = unitsPerSrc; 38405b261ecSmrg if (n > w) 38505b261ecSmrg n = w; 38605b261ecSmrg } 38705b261ecSmrg } 38805b261ecSmrg /* 38905b261ecSmrg * Consume stipple bits for endmask 39005b261ecSmrg */ 39105b261ecSmrg if (endmask) 39205b261ecSmrg { 39305b261ecSmrg if (endNeedsLoad) 39405b261ecSmrg { 39505b261ecSmrg LoadBits; 39605b261ecSmrg } 39705b261ecSmrg#if FB_UNIT > 32 39805b261ecSmrg if (pixelsPerDst == 16) 39905b261ecSmrg mask = FbStipple16Bits(FbLeftStipBits(bits,16)); 40005b261ecSmrg else 40105b261ecSmrg#endif 40205b261ecSmrg mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)]; 40305b261ecSmrg#ifndef FBNOPIXADDR 40405b261ecSmrg if (fbLane) 40505b261ecSmrg { 40605b261ecSmrg fbTransparentSpan (dst, mask & endmask, fgxor, 1); 40705b261ecSmrg } 40805b261ecSmrg else 40905b261ecSmrg#endif 41005b261ecSmrg { 41105b261ecSmrg if (mask || !transparent) 41205b261ecSmrg FbDoRightMaskByteStippleRRop (dst, mask, 41305b261ecSmrg fgand, fgxor, bgand, bgxor, 41405b261ecSmrg endbyte, endmask); 41505b261ecSmrg } 41605b261ecSmrg } 41705b261ecSmrg dst += dstStride; 41805b261ecSmrg src += srcStride; 41905b261ecSmrg } 42005b261ecSmrg} 42105b261ecSmrg 42205b261ecSmrg#ifdef FB_24BIT 42305b261ecSmrg 42405b261ecSmrg/* 42505b261ecSmrg * Crufty macros to initialize the mask array, most of this 42605b261ecSmrg * is to avoid compile-time warnings about shift overflow 42705b261ecSmrg */ 42805b261ecSmrg 42905b261ecSmrg#if BITMAP_BIT_ORDER == MSBFirst 43005b261ecSmrg#define Mask24Pos(x,r) ((x)*24-(r)) 43105b261ecSmrg#else 43205b261ecSmrg#define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0)) 43305b261ecSmrg#endif 43405b261ecSmrg 43505b261ecSmrg#define Mask24Neg(x,r) (Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0) 43605b261ecSmrg#define Mask24Check(x,r) (Mask24Pos(x,r) < 0 ? 0 : \ 43705b261ecSmrg Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r)) 43805b261ecSmrg 43905b261ecSmrg#define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \ 44005b261ecSmrg (Mask24Pos(x,r) < 0 ? \ 4419ace9065Smrg 0xffffffU >> Mask24Neg (x,r) : \ 4429ace9065Smrg 0xffffffU << Mask24Check(x,r)) : 0) 44305b261ecSmrg 44405b261ecSmrg#define SelMask24(b,n,r) ((((b) >> n) & 1) * Mask24(n,r)) 44505b261ecSmrg 44605b261ecSmrg/* 44705b261ecSmrg * Untested for MSBFirst or FB_UNIT == 32 44805b261ecSmrg */ 44905b261ecSmrg 45005b261ecSmrg#if FB_UNIT == 64 45105b261ecSmrg#define C4_24(b,r) \ 45205b261ecSmrg (SelMask24(b,0,r) | \ 45305b261ecSmrg SelMask24(b,1,r) | \ 45405b261ecSmrg SelMask24(b,2,r) | \ 45505b261ecSmrg SelMask24(b,3,r)) 45605b261ecSmrg 45705b261ecSmrg#define FbStip24New(rot) (2 + (rot != 0)) 45805b261ecSmrg#define FbStip24Len 4 45905b261ecSmrg 46005b261ecSmrgconst FbBits fbStipple24Bits[3][1 << FbStip24Len] = { 46105b261ecSmrg /* rotate 0 */ 46205b261ecSmrg { 46305b261ecSmrg C4_24( 0, 0), C4_24( 1, 0), C4_24( 2, 0), C4_24( 3, 0), 46405b261ecSmrg C4_24( 4, 0), C4_24( 5, 0), C4_24( 6, 0), C4_24( 7, 0), 46505b261ecSmrg C4_24( 8, 0), C4_24( 9, 0), C4_24(10, 0), C4_24(11, 0), 46605b261ecSmrg C4_24(12, 0), C4_24(13, 0), C4_24(14, 0), C4_24(15, 0), 46705b261ecSmrg }, 46805b261ecSmrg /* rotate 8 */ 46905b261ecSmrg { 47005b261ecSmrg C4_24( 0, 8), C4_24( 1, 8), C4_24( 2, 8), C4_24( 3, 8), 47105b261ecSmrg C4_24( 4, 8), C4_24( 5, 8), C4_24( 6, 8), C4_24( 7, 8), 47205b261ecSmrg C4_24( 8, 8), C4_24( 9, 8), C4_24(10, 8), C4_24(11, 8), 47305b261ecSmrg C4_24(12, 8), C4_24(13, 8), C4_24(14, 8), C4_24(15, 8), 47405b261ecSmrg }, 47505b261ecSmrg /* rotate 16 */ 47605b261ecSmrg { 47705b261ecSmrg C4_24( 0,16), C4_24( 1,16), C4_24( 2,16), C4_24( 3,16), 47805b261ecSmrg C4_24( 4,16), C4_24( 5,16), C4_24( 6,16), C4_24( 7,16), 47905b261ecSmrg C4_24( 8,16), C4_24( 9,16), C4_24(10,16), C4_24(11,16), 48005b261ecSmrg C4_24(12,16), C4_24(13,16), C4_24(14,16), C4_24(15,16), 48105b261ecSmrg } 48205b261ecSmrg}; 48305b261ecSmrg 48405b261ecSmrg#endif 48505b261ecSmrg 48605b261ecSmrg#if FB_UNIT == 32 48705b261ecSmrg#define C2_24(b,r) \ 48805b261ecSmrg (SelMask24(b,0,r) | \ 48905b261ecSmrg SelMask24(b,1,r)) 49005b261ecSmrg 49105b261ecSmrg#define FbStip24Len 2 49205b261ecSmrg#if BITMAP_BIT_ORDER == MSBFirst 49305b261ecSmrg#define FbStip24New(rot) (1 + (rot == 0)) 49405b261ecSmrg#else 49505b261ecSmrg#define FbStip24New(rot) (1 + (rot == 8)) 49605b261ecSmrg#endif 49705b261ecSmrg 49805b261ecSmrgconst FbBits fbStipple24Bits[3][1 << FbStip24Len] = { 49905b261ecSmrg /* rotate 0 */ 50005b261ecSmrg { 50105b261ecSmrg C2_24( 0, 0), C2_24 ( 1, 0), C2_24 ( 2, 0), C2_24 ( 3, 0), 50205b261ecSmrg }, 50305b261ecSmrg /* rotate 8 */ 50405b261ecSmrg { 50505b261ecSmrg C2_24( 0, 8), C2_24 ( 1, 8), C2_24 ( 2, 8), C2_24 ( 3, 8), 50605b261ecSmrg }, 50705b261ecSmrg /* rotate 16 */ 50805b261ecSmrg { 50905b261ecSmrg C2_24( 0,16), C2_24 ( 1,16), C2_24 ( 2,16), C2_24 ( 3,16), 51005b261ecSmrg } 51105b261ecSmrg}; 51205b261ecSmrg#endif 51305b261ecSmrg 51405b261ecSmrg#if BITMAP_BIT_ORDER == LSBFirst 51505b261ecSmrg 51605b261ecSmrg#define FbMergeStip24Bits(left, right, new) \ 51705b261ecSmrg (FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new)))) 51805b261ecSmrg 51905b261ecSmrg#define FbMergePartStip24Bits(left, right, llen, rlen) \ 52005b261ecSmrg (left | FbStipRight(right, llen)) 52105b261ecSmrg 52205b261ecSmrg#else 52305b261ecSmrg 52405b261ecSmrg#define FbMergeStip24Bits(left, right, new) \ 52505b261ecSmrg ((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right) 52605b261ecSmrg 52705b261ecSmrg#define FbMergePartStip24Bits(left, right, llen, rlen) \ 52805b261ecSmrg (FbStipLeft(left, rlen) | right) 52905b261ecSmrg 53005b261ecSmrg#endif 53105b261ecSmrg 53205b261ecSmrg#define fbFirstStipBits(len,stip) {\ 53305b261ecSmrg int __len = (len); \ 53405b261ecSmrg if (len <= remain) { \ 53505b261ecSmrg stip = FbLeftStipBits(bits, len); \ 53605b261ecSmrg } else { \ 53705b261ecSmrg stip = FbLeftStipBits(bits, remain); \ 53805b261ecSmrg bits = (src < srcEnd ? READ(src++) : 0); \ 53905b261ecSmrg __len = (len) - remain; \ 54005b261ecSmrg stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \ 54105b261ecSmrg remain, __len); \ 54205b261ecSmrg remain = FB_STIP_UNIT; \ 54305b261ecSmrg } \ 54405b261ecSmrg bits = FbStipLeft (bits, __len); \ 54505b261ecSmrg remain -= __len; \ 54605b261ecSmrg} 54705b261ecSmrg 54805b261ecSmrg#define fbInitStipBits(offset,len,stip) {\ 54905b261ecSmrg bits = FbStipLeft (READ(src++),offset); \ 55005b261ecSmrg remain = FB_STIP_UNIT - offset; \ 55105b261ecSmrg fbFirstStipBits(len,stip); \ 55205b261ecSmrg stip = FbMergeStip24Bits (0, stip, len); \ 55305b261ecSmrg} 55405b261ecSmrg 55505b261ecSmrg#define fbNextStipBits(rot,stip) {\ 55605b261ecSmrg int __new = FbStip24New(rot); \ 55705b261ecSmrg FbStip __right; \ 55805b261ecSmrg fbFirstStipBits(__new, __right); \ 55905b261ecSmrg stip = FbMergeStip24Bits (stip, __right, __new); \ 56005b261ecSmrg rot = FbNext24Rot (rot); \ 56105b261ecSmrg} 56205b261ecSmrg 56305b261ecSmrg/* 56405b261ecSmrg * Use deep mask tables that incorporate rotation, pull 56505b261ecSmrg * a variable number of bits out of the stipple and 56605b261ecSmrg * reuse the right bits as needed for the next write 56705b261ecSmrg * 56805b261ecSmrg * Yes, this is probably too much code, but most 24-bpp screens 56905b261ecSmrg * have no acceleration so this code is used for stipples, copyplane 57005b261ecSmrg * and text 57105b261ecSmrg */ 57205b261ecSmrgvoid 57305b261ecSmrgfbBltOne24 (FbStip *srcLine, 57405b261ecSmrg FbStride srcStride, /* FbStip units per scanline */ 57505b261ecSmrg int srcX, /* bit position of source */ 57605b261ecSmrg FbBits *dst, 57705b261ecSmrg FbStride dstStride, /* FbBits units per scanline */ 57805b261ecSmrg int dstX, /* bit position of dest */ 57905b261ecSmrg int dstBpp, /* bits per destination unit */ 58005b261ecSmrg 58105b261ecSmrg int width, /* width in bits of destination */ 58205b261ecSmrg int height, /* height in scanlines */ 58305b261ecSmrg 58405b261ecSmrg FbBits fgand, /* rrop values */ 58505b261ecSmrg FbBits fgxor, 58605b261ecSmrg FbBits bgand, 58705b261ecSmrg FbBits bgxor) 58805b261ecSmrg{ 58905b261ecSmrg FbStip *src, *srcEnd; 59005b261ecSmrg FbBits leftMask, rightMask, mask; 59105b261ecSmrg int nlMiddle, nl; 59205b261ecSmrg FbStip stip, bits; 59305b261ecSmrg int remain; 59405b261ecSmrg int dstS; 59505b261ecSmrg int firstlen; 59605b261ecSmrg int rot0, rot; 59705b261ecSmrg int nDst; 59805b261ecSmrg 59905b261ecSmrg /* 60005b261ecSmrg * Do not read past the end of the buffer! 60105b261ecSmrg */ 60205b261ecSmrg srcEnd = srcLine + height * srcStride; 60305b261ecSmrg 60405b261ecSmrg srcLine += srcX >> FB_STIP_SHIFT; 60505b261ecSmrg dst += dstX >> FB_SHIFT; 60605b261ecSmrg srcX &= FB_STIP_MASK; 60705b261ecSmrg dstX &= FB_MASK; 60805b261ecSmrg rot0 = FbFirst24Rot (dstX); 60905b261ecSmrg 61005b261ecSmrg FbMaskBits (dstX, width, leftMask, nlMiddle, rightMask); 61105b261ecSmrg 61205b261ecSmrg dstS = (dstX + 23) / 24; 61305b261ecSmrg firstlen = FbStip24Len - dstS; 61405b261ecSmrg 61505b261ecSmrg nDst = nlMiddle; 61605b261ecSmrg if (leftMask) 61705b261ecSmrg nDst++; 61805b261ecSmrg dstStride -= nDst; 61905b261ecSmrg 62005b261ecSmrg /* opaque copy */ 62105b261ecSmrg if (bgand == 0 && fgand == 0) 62205b261ecSmrg { 62305b261ecSmrg while (height--) 62405b261ecSmrg { 62505b261ecSmrg rot = rot0; 62605b261ecSmrg src = srcLine; 62705b261ecSmrg srcLine += srcStride; 62805b261ecSmrg fbInitStipBits (srcX,firstlen, stip); 62905b261ecSmrg if (leftMask) 63005b261ecSmrg { 63105b261ecSmrg mask = fbStipple24Bits[rot >> 3][stip]; 63205b261ecSmrg WRITE(dst, (READ(dst) & ~leftMask) | 63305b261ecSmrg (FbOpaqueStipple (mask, 63405b261ecSmrg FbRot24(fgxor, rot), 63505b261ecSmrg FbRot24(bgxor, rot)) 63605b261ecSmrg & leftMask)); 63705b261ecSmrg dst++; 63805b261ecSmrg fbNextStipBits(rot,stip); 63905b261ecSmrg } 64005b261ecSmrg nl = nlMiddle; 64105b261ecSmrg while (nl--) 64205b261ecSmrg { 64305b261ecSmrg mask = fbStipple24Bits[rot>>3][stip]; 64405b261ecSmrg WRITE(dst, FbOpaqueStipple (mask, 64505b261ecSmrg FbRot24(fgxor, rot), 64605b261ecSmrg FbRot24(bgxor, rot))); 64705b261ecSmrg dst++; 64805b261ecSmrg fbNextStipBits(rot,stip); 64905b261ecSmrg } 65005b261ecSmrg if (rightMask) 65105b261ecSmrg { 65205b261ecSmrg mask = fbStipple24Bits[rot >> 3][stip]; 65305b261ecSmrg WRITE(dst, (READ(dst) & ~rightMask) | 65405b261ecSmrg (FbOpaqueStipple (mask, 65505b261ecSmrg FbRot24(fgxor, rot), 65605b261ecSmrg FbRot24(bgxor, rot)) 65705b261ecSmrg & rightMask)); 65805b261ecSmrg } 65905b261ecSmrg dst += dstStride; 66005b261ecSmrg src += srcStride; 66105b261ecSmrg } 66205b261ecSmrg } 66305b261ecSmrg /* transparent copy */ 66405b261ecSmrg else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0) 66505b261ecSmrg { 66605b261ecSmrg while (height--) 66705b261ecSmrg { 66805b261ecSmrg rot = rot0; 66905b261ecSmrg src = srcLine; 67005b261ecSmrg srcLine += srcStride; 67105b261ecSmrg fbInitStipBits (srcX, firstlen, stip); 67205b261ecSmrg if (leftMask) 67305b261ecSmrg { 67405b261ecSmrg if (stip) 67505b261ecSmrg { 67605b261ecSmrg mask = fbStipple24Bits[rot >> 3][stip] & leftMask; 67705b261ecSmrg WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 67805b261ecSmrg } 67905b261ecSmrg dst++; 68005b261ecSmrg fbNextStipBits (rot, stip); 68105b261ecSmrg } 68205b261ecSmrg nl = nlMiddle; 68305b261ecSmrg while (nl--) 68405b261ecSmrg { 68505b261ecSmrg if (stip) 68605b261ecSmrg { 68705b261ecSmrg mask = fbStipple24Bits[rot>>3][stip]; 68805b261ecSmrg WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor,rot) & mask)); 68905b261ecSmrg } 69005b261ecSmrg dst++; 69105b261ecSmrg fbNextStipBits (rot, stip); 69205b261ecSmrg } 69305b261ecSmrg if (rightMask) 69405b261ecSmrg { 69505b261ecSmrg if (stip) 69605b261ecSmrg { 69705b261ecSmrg mask = fbStipple24Bits[rot >> 3][stip] & rightMask; 69805b261ecSmrg WRITE(dst, (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 69905b261ecSmrg } 70005b261ecSmrg } 70105b261ecSmrg dst += dstStride; 70205b261ecSmrg } 70305b261ecSmrg } 70405b261ecSmrg else 70505b261ecSmrg { 70605b261ecSmrg while (height--) 70705b261ecSmrg { 70805b261ecSmrg rot = rot0; 70905b261ecSmrg src = srcLine; 71005b261ecSmrg srcLine += srcStride; 71105b261ecSmrg fbInitStipBits (srcX, firstlen, stip); 71205b261ecSmrg if (leftMask) 71305b261ecSmrg { 71405b261ecSmrg mask = fbStipple24Bits[rot >> 3][stip]; 71505b261ecSmrg WRITE(dst, FbStippleRRopMask (READ(dst), mask, 71605b261ecSmrg FbRot24(fgand, rot), 71705b261ecSmrg FbRot24(fgxor, rot), 71805b261ecSmrg FbRot24(bgand, rot), 71905b261ecSmrg FbRot24(bgxor, rot), 72005b261ecSmrg leftMask)); 72105b261ecSmrg dst++; 72205b261ecSmrg fbNextStipBits(rot,stip); 72305b261ecSmrg } 72405b261ecSmrg nl = nlMiddle; 72505b261ecSmrg while (nl--) 72605b261ecSmrg { 72705b261ecSmrg mask = fbStipple24Bits[rot >> 3][stip]; 72805b261ecSmrg WRITE(dst, FbStippleRRop (READ(dst), mask, 72905b261ecSmrg FbRot24(fgand, rot), 73005b261ecSmrg FbRot24(fgxor, rot), 73105b261ecSmrg FbRot24(bgand, rot), 73205b261ecSmrg FbRot24(bgxor, rot))); 73305b261ecSmrg dst++; 73405b261ecSmrg fbNextStipBits(rot,stip); 73505b261ecSmrg } 73605b261ecSmrg if (rightMask) 73705b261ecSmrg { 73805b261ecSmrg mask = fbStipple24Bits[rot >> 3][stip]; 73905b261ecSmrg WRITE(dst, FbStippleRRopMask (READ(dst), mask, 74005b261ecSmrg FbRot24(fgand, rot), 74105b261ecSmrg FbRot24(fgxor, rot), 74205b261ecSmrg FbRot24(bgand, rot), 74305b261ecSmrg FbRot24(bgxor, rot), 74405b261ecSmrg rightMask)); 74505b261ecSmrg } 74605b261ecSmrg dst += dstStride; 74705b261ecSmrg } 74805b261ecSmrg } 74905b261ecSmrg} 75005b261ecSmrg#endif 75105b261ecSmrg 75205b261ecSmrg/* 75305b261ecSmrg * Not very efficient, but simple -- copy a single plane 75405b261ecSmrg * from an N bit image to a 1 bit image 75505b261ecSmrg */ 75605b261ecSmrg 75705b261ecSmrgvoid 75805b261ecSmrgfbBltPlane (FbBits *src, 75905b261ecSmrg FbStride srcStride, 76005b261ecSmrg int srcX, 76105b261ecSmrg int srcBpp, 76205b261ecSmrg 76305b261ecSmrg FbStip *dst, 76405b261ecSmrg FbStride dstStride, 76505b261ecSmrg int dstX, 76605b261ecSmrg 76705b261ecSmrg int width, 76805b261ecSmrg int height, 76905b261ecSmrg 77005b261ecSmrg FbStip fgand, 77105b261ecSmrg FbStip fgxor, 77205b261ecSmrg FbStip bgand, 77305b261ecSmrg FbStip bgxor, 77405b261ecSmrg Pixel planeMask) 77505b261ecSmrg{ 77605b261ecSmrg FbBits *s; 77705b261ecSmrg FbBits pm; 77805b261ecSmrg FbBits srcMask; 77905b261ecSmrg FbBits srcMaskFirst; 78005b261ecSmrg FbBits srcMask0 = 0; 78105b261ecSmrg FbBits srcBits; 78205b261ecSmrg 78305b261ecSmrg FbStip dstBits; 78405b261ecSmrg FbStip *d; 78505b261ecSmrg FbStip dstMask; 78605b261ecSmrg FbStip dstMaskFirst; 78705b261ecSmrg FbStip dstUnion; 78805b261ecSmrg int w; 78905b261ecSmrg int wt; 79005b261ecSmrg int rot0; 79105b261ecSmrg 79205b261ecSmrg if (!width) 79305b261ecSmrg return; 79405b261ecSmrg 79505b261ecSmrg src += srcX >> FB_SHIFT; 79605b261ecSmrg srcX &= FB_MASK; 79705b261ecSmrg 79805b261ecSmrg dst += dstX >> FB_STIP_SHIFT; 79905b261ecSmrg dstX &= FB_STIP_MASK; 80005b261ecSmrg 80105b261ecSmrg w = width / srcBpp; 80205b261ecSmrg 80305b261ecSmrg pm = fbReplicatePixel (planeMask, srcBpp); 80405b261ecSmrg#ifdef FB_24BIT 80505b261ecSmrg if (srcBpp == 24) 80605b261ecSmrg { 80705b261ecSmrg int w = 24; 80805b261ecSmrg 80905b261ecSmrg rot0 = FbFirst24Rot (srcX); 81005b261ecSmrg if (srcX + w > FB_UNIT) 81105b261ecSmrg w = FB_UNIT - srcX; 81205b261ecSmrg srcMaskFirst = FbRot24(pm,rot0) & FbBitsMask(srcX,w); 81305b261ecSmrg } 81405b261ecSmrg else 81505b261ecSmrg#endif 81605b261ecSmrg { 81705b261ecSmrg rot0 = 0; 81805b261ecSmrg srcMaskFirst = pm & FbBitsMask(srcX, srcBpp); 81905b261ecSmrg srcMask0 = pm & FbBitsMask(0, srcBpp); 82005b261ecSmrg } 82105b261ecSmrg 82205b261ecSmrg dstMaskFirst = FbStipMask(dstX,1); 82305b261ecSmrg while (height--) 82405b261ecSmrg { 82505b261ecSmrg d = dst; 82605b261ecSmrg dst += dstStride; 82705b261ecSmrg s = src; 82805b261ecSmrg src += srcStride; 82905b261ecSmrg 83005b261ecSmrg srcMask = srcMaskFirst; 83105b261ecSmrg#ifdef FB_24BIT 83205b261ecSmrg if (srcBpp == 24) 83305b261ecSmrg srcMask0 = FbRot24(pm,rot0) & FbBitsMask(0, srcBpp); 83405b261ecSmrg#endif 83505b261ecSmrg srcBits = READ(s++); 83605b261ecSmrg 83705b261ecSmrg dstMask = dstMaskFirst; 83805b261ecSmrg dstUnion = 0; 83905b261ecSmrg dstBits = 0; 84005b261ecSmrg 84105b261ecSmrg wt = w; 84205b261ecSmrg 84305b261ecSmrg while (wt--) 84405b261ecSmrg { 84505b261ecSmrg if (!srcMask) 84605b261ecSmrg { 84705b261ecSmrg srcBits = READ(s++); 84805b261ecSmrg#ifdef FB_24BIT 84905b261ecSmrg if (srcBpp == 24) 85005b261ecSmrg srcMask0 = FbNext24Pix(srcMask0) & FbBitsMask(0,24); 85105b261ecSmrg#endif 85205b261ecSmrg srcMask = srcMask0; 85305b261ecSmrg } 85405b261ecSmrg if (!dstMask) 85505b261ecSmrg { 85605b261ecSmrg WRITE(d, FbStippleRRopMask(READ(d), dstBits, 85705b261ecSmrg fgand, fgxor, bgand, bgxor, 85805b261ecSmrg dstUnion)); 85905b261ecSmrg d++; 86005b261ecSmrg dstMask = FbStipMask(0,1); 86105b261ecSmrg dstUnion = 0; 86205b261ecSmrg dstBits = 0; 86305b261ecSmrg } 86405b261ecSmrg if (srcBits & srcMask) 86505b261ecSmrg dstBits |= dstMask; 86605b261ecSmrg dstUnion |= dstMask; 86705b261ecSmrg if (srcBpp == FB_UNIT) 86805b261ecSmrg srcMask = 0; 86905b261ecSmrg else 87005b261ecSmrg srcMask = FbScrRight(srcMask,srcBpp); 87105b261ecSmrg dstMask = FbStipRight(dstMask,1); 87205b261ecSmrg } 87305b261ecSmrg if (dstUnion) 87405b261ecSmrg WRITE(d, FbStippleRRopMask(READ(d),dstBits, 87505b261ecSmrg fgand, fgxor, bgand, bgxor, 87605b261ecSmrg dstUnion)); 87705b261ecSmrg } 87805b261ecSmrg} 87905b261ecSmrg 880