diff options
Diffstat (limited to 'cfb/cfbblt.c')
-rw-r--r-- | cfb/cfbblt.c | 349 |
1 files changed, 324 insertions, 25 deletions
diff --git a/cfb/cfbblt.c b/cfb/cfbblt.c index f87acc03d..aafe44669 100644 --- a/cfb/cfbblt.c +++ b/cfb/cfbblt.c @@ -1,6 +1,7 @@ /* * cfb copy area */ +/* $XFree86: xc/programs/Xserver/cfb/cfbblt.c,v 3.12 2001/12/14 19:59:21 dawes Exp $ */ /* @@ -31,6 +32,8 @@ Author: Keith Packard */ /* $Xorg: cfbblt.c,v 1.4 2001/02/09 02:04:37 xorgcvs Exp $ */ +/* 24-bit bug fixes: Peter Wainwright, 1998/11/28 */ + #include "X.h" #include "Xmd.h" #include "Xproto.h" @@ -55,6 +58,65 @@ Author: Keith Packard #define DO_MEMCPY #endif +/* ................................................. */ +/* SPECIAL CODE FOR 24 BITS by Peter Wainwright */ + +#if PSZ == 24 && (MROP) == 0 + +/* The default macros are defined in mergerop.h, and none of them are + really appropriate for what we want to do. + + There are two ways of fixing this: either define SLOW_24BIT_COPY + to copy pixel by pixel, or (by default) use the following macros + modified from mergerop.h + + MROP_SOLID and MROP_MASK are defined for each of the operations, + i.e. each value of MROP. + + There are special cases for Mcopy, McopyInverted, Mxor, and Mor. + There is a completely generic version for MROP=0, and a simplified + generic version which works for (Mcopy|Mxor|MandReverse|Mor). + + However, the generic version does not work for the 24-bit case + because the pixels cannot be packed exactly into a machine word (32 + bits). + + Alternative macros MROP_SOLID24 and MROP_MASK24 are provided for + the 24-bit case. However, these each copy a single *pixel*, not a + single machine word. They take an rvalue source pixel, an lvalue + destination, and the pixel index. The latter is used to find the + position of the pixel data within the two words *dst and *(dst+1). + + Further macros MROP_SOLID24P and MROP_MASK24P are used to copy from + an lvalue source to an lvalue destination. MROP_PIXEL24 is used to + assemble the source pixel from the adjacent words *src and + *(src+1), and this is then split between the destination words + using the non-P macros above. + + But we want to copy entire words for the sake of efficiency. + Unfortunately if a plane mask is specified this must be shifted + from one word to the next. Fortunately the pattern repeats after 3 + words, so we unroll the planemask here and redefine MROP_SOLID + and MROP_MASK. */ + + +#endif /* MROP == 0 && PSZ == 24 */ + +/* ................................................. */ + +#if PSZ == 24 +#define BYPP 3 +#if PGSZ == 32 +#define P3W 4 /* pixels in 3 machine words */ +#define PAM 3 /* pixel align mask; PAM = P3W -1 */ +#define P2WSH 2 +#else +#define P3W 8 /* pixels in 3 machine words */ +#define PAM 7 /* pixel align mask; PAM = P3W -1 */ +#define P2WSH 3 +#endif +#endif + void MROP_NAME(cfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask) DrawablePtr pSrc, pDst; @@ -63,7 +125,7 @@ MROP_NAME(cfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask) DDXPointPtr pptSrc; unsigned long planemask; { - unsigned long *psrcBase, *pdstBase; + CfbBits *psrcBase, *pdstBase; /* start of src and dst bitmaps */ int widthSrc, widthDst; /* add to get to same position in next line */ @@ -79,31 +141,42 @@ MROP_NAME(cfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask) int xdir; /* 1 = left right, -1 = right left/ */ int ydir; /* 1 = top down, -1 = bottom up */ - unsigned long *psrcLine, *pdstLine; + CfbBits *psrcLine, *pdstLine; /* pointers to line with current src and dst */ - register unsigned long *psrc;/* pointer to current src longword */ - register unsigned long *pdst;/* pointer to current dst longword */ + register CfbBits *psrc;/* pointer to current src longword */ + register CfbBits *pdst;/* pointer to current dst longword */ MROP_DECLARE_REG() /* following used for looping through a line */ - unsigned long startmask, endmask; /* masks for writing ends of dst */ + CfbBits startmask, endmask; /* masks for writing ends of dst */ int nlMiddle; /* whole longwords in dst */ int xoffSrc, xoffDst; - register int leftShift, rightShift; - register unsigned long bits; - register unsigned long bits1; register int nl; /* temp copy of nlMiddle */ - - /* place to store full source word */ - int nstart; /* number of ragged bits at start of dst */ - int nend; /* number of ragged bits at end of dst */ - int srcStartOver; /* pulling nstart bits from src - overflows into the next word? */ int careful; - int tmpSrc; - MROP_INITIALIZE(alu,planemask); +#if (PSZ != 24) || (MROP != 0) + register int leftShift, rightShift; + register CfbBits bits; + register CfbBits bits1; +#endif + +#if PSZ == 24 +#ifdef DO_MEMCPY + int w2; +#endif + +#if MROP == 0 + unsigned char *psrcBaseByte, *pdstBaseByte; + int widthSrcBytes, widthDstBytes; + + cfbGetByteWidthAndPointer (pSrc, widthSrcBytes, psrcBaseByte) + + cfbGetByteWidthAndPointer (pDst, widthDstBytes, pdstBaseByte) +#endif +#endif + + MROP_INITIALIZE(alu,planemask) cfbGetLongWidthAndPointer (pSrc, widthSrc, psrcBase) @@ -222,6 +295,11 @@ MROP_NAME(cfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask) w = pbox->x2 - pbox->x1; h = pbox->y2 - pbox->y1; +#if PSZ == 24 +#ifdef DO_MEMCPY + w2 = w * BYPP; +#endif +#endif if (ydir == -1) /* start at last scanline of rectangle */ { psrcLine = psrcBase + ((pptSrc->y+h-1) * -widthSrc); @@ -232,7 +310,11 @@ MROP_NAME(cfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask) psrcLine = psrcBase + (pptSrc->y * widthSrc); pdstLine = pdstBase + (pbox->y1 * widthDst); } +#if PSZ == 24 + if (w == 1 && ((pbox->x1 & PAM) == 0 || (pbox->x1 & PAM) == PAM)) +#else if ((pbox->x1 & PIM) + w <= PPW) +#endif { maskpartialbits (pbox->x1, w, endmask); startmask = 0; @@ -243,58 +325,149 @@ MROP_NAME(cfbDoBitblt)(pSrc, pDst, alu, prgnDst, pptSrc, planemask) maskbits(pbox->x1, w, startmask, endmask, nlMiddle); } +#if PSZ == 24 +#if 0 + nlMiddle = w - (pbox->x2 &PAM);; + if(pbox->x1 & PAM){ + nlMiddle -= (PAM+1 - (pbox->x1 &PAM)); + } + nlMiddle >>= P2WSH; + if(nlMiddle < 0) + nlMiddle = 0; +#endif +#endif + #ifdef DO_MEMCPY /* If the src and dst scanline don't overlap, do forward case. */ if ((xdir == 1) || (pptSrc->y != pbox->y1) || (pptSrc->x + w <= pbox->x1)) { +#if PSZ == 24 + char *psrc = (char *) psrcLine + (pptSrc->x * BYPP); + char *pdst = (char *) pdstLine + (pbox->x1 * BYPP); +#else char *psrc = (char *) psrcLine + pptSrc->x; char *pdst = (char *) pdstLine + pbox->x1; +#endif while (h--) { +#if PSZ == 24 + memcpy(pdst, psrc, w2); +#else memcpy(pdst, psrc, w); - pdst += widthDst << 2; - psrc += widthSrc << 2; +#endif + pdst += widthDst << PWSH; + psrc += widthSrc << PWSH; } } #else /* ! DO_MEMCPY */ if (xdir == 1) { +#if PSZ == 24 && MROP == 0 + /* Note: x is a pixel number; the byte offset is 3*x; + therefore the offset within a word is (3*x) & 3 == + (4*x-x) & 3 == (-x) & 3. The offsets therefore + DECREASE by 1 for each pixel. + */ + xoffSrc = ( - pptSrc->x) & PAM; + xoffDst = ( - pbox->x1) & PAM; +#if 1 + if((int)xoffSrc != (int)xoffDst /* Alignments must be same. */ + || ((widthDstBytes & PAM) != (widthSrcBytes & PAM) && h > 1)) +#else + if(1) +#endif + /* Width also must be same, if hight > 1 */ + { + /* ...otherwise, pixel by pixel operation */ + while (h--) + { + register int i, si, sii, di; + + for (i = 0, si = pptSrc->x, di = pbox->x1; + i < w; + i++, si++, di++) { + psrc = psrcLine + ((si * BYPP) >> P2WSH); + pdst = pdstLine + ((di * BYPP) >> P2WSH); + sii = (si & 3); + MROP_SOLID24P(psrc, pdst, sii, di); + } + pdstLine += widthDst; + psrcLine += widthSrc; + } + } + else +#endif + { + +#if PSZ == 24 + +#if MROP != 0 + xoffSrc = ( - pptSrc->x) & PAM; + xoffDst = ( - pbox->x1) & PAM; +#endif + pdstLine += (pbox->x1 * BYPP) >> P2WSH; + psrcLine += (pptSrc->x * BYPP) >> P2WSH; +#else xoffSrc = pptSrc->x & PIM; xoffDst = pbox->x1 & PIM; pdstLine += (pbox->x1 >> PWSH); psrcLine += (pptSrc->x >> PWSH); +#endif #ifdef DO_UNALIGNED_BITBLT nl = xoffSrc - xoffDst; - psrcLine = (unsigned long *) + psrcLine = (CfbBits *) (((unsigned char *) psrcLine) + nl); #else +#if PSZ == 24 && MROP == 0 + /* alredy satisfied */ +#else if (xoffSrc == xoffDst) #endif +#endif { while (h--) { +#if PSZ == 24 && MROP == 0 + register int index; + register int im3; +#endif /* PSZ == 24 && MROP == 0 */ psrc = psrcLine; pdst = pdstLine; pdstLine += widthDst; psrcLine += widthSrc; +#if PSZ == 24 && MROP == 0 + index = (int)(pdst - pdstBase); + im3 = index % 3; +#endif /* PSZ == 24 && MROP == 0 */ if (startmask) { +#if PSZ == 24 && MROP == 0 + *pdst = DoMaskMergeRop24u(*psrc, *pdst, startmask, im3); + index++; + im3 = index % 3; +#else /* PSZ != 24 || MROP != 0 */ *pdst = MROP_MASK(*psrc, *pdst, startmask); +#endif /* PSZ == 24 && MROP == 0 */ psrc++; pdst++; } - nl = nlMiddle; + nl = nlMiddle; #ifdef LARGE_INSTRUCTION_CACHE #ifdef FAST_CONSTANT_OFFSET_MODE psrc += nl & (UNROLL-1); pdst += nl & (UNROLL-1); +#if PSZ == 24 && MROP == 0 +#define BodyOdd(n) pdst[-n] = DoMergeRop24u(psrc[-n], pdst[-n], ((int)(pdst - n - pdstBase))%3); +#define BodyEven(n) pdst[-n] = DoMergeRop24u(psrc[-n], pdst[-n], ((int)(pdst - n - pdstBase))%3); +#else /* PSZ != 24 || MROP != 0 */ #define BodyOdd(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]); #define BodyEven(n) pdst[-n] = MROP_SOLID (psrc[-n], pdst[-n]); +#endif /* PSZ == 24 && MROP == 0 */ #define LoopReset \ pdst += UNROLL; \ @@ -302,8 +475,13 @@ psrc += UNROLL; #else +#if PSZ == 24 && MROP == 0 +#define BodyOdd(n) *pdst = DoMergeRop24u(*psrc, *pdst, im3); pdst++; psrc++; index++; im3 = index % 3; +#define BodyEven(n) BodyOdd(n) +#else /* PSZ != 24 || MROP != 0 */ #define BodyOdd(n) *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++; #define BodyEven(n) BodyOdd(n) +#endif /* PSZ == 24 && MROP == 0 */ #define LoopReset ; @@ -333,34 +511,55 @@ psrc += UNROLL; while (nl--) *pdst++ = *psrc++; #endif +#if 0 /*PSZ == 24 && MROP == 0*/ + DuffL(nl, label1, + *pdst = DoMergeRop24u(*psrc, *pdst, im3); + pdst++; psrc++; index++;im3 = index % 3;) +#else /* !(PSZ == 24 && MROP == 0) */ DuffL(nl, label1, *pdst = MROP_SOLID (*psrc, *pdst); pdst++; psrc++;) +#endif /* PSZ == 24 && MROP == 0 */ #endif if (endmask) +#if PSZ == 24 && MROP == 0 + *pdst = DoMaskMergeRop24u(*psrc, *pdst, endmask, (int)(pdst - pdstBase) % 3); +#else /* !(PSZ == 24 && MROP == 0) */ *pdst = MROP_MASK(*psrc, *pdst, endmask); +#endif /* PSZ == 24 && MROP == 0 */ } } #ifndef DO_UNALIGNED_BITBLT - else +#if PSZ == 24 && MROP == 0 + /* can not happen */ +#else /* !(PSZ == 24 && MROP == 0) */ + else /* xoffSrc != xoffDst */ { if (xoffSrc > xoffDst) { +#if PSZ == 24 + leftShift = (xoffSrc - xoffDst) << 3; +#else #if PGSZ == 32 leftShift = (xoffSrc - xoffDst) << (5 - PWSH); #else /* PGSZ == 64 */ leftShift = (xoffSrc - xoffDst) << (6 - PWSH); #endif /* PGSZ */ +#endif rightShift = PGSZ - leftShift; } else { +#if PSZ == 24 + rightShift = (xoffDst - xoffSrc) << 3; +#else #if PGSZ == 32 rightShift = (xoffDst - xoffSrc) << (5 - PWSH); #else /* PGSZ == 64 */ rightShift = (xoffDst - xoffSrc) << (6 - PWSH); #endif /* PGSZ */ +#endif leftShift = PGSZ - rightShift; } while (h--) @@ -381,7 +580,6 @@ psrc += UNROLL; pdst++; } nl = nlMiddle; - #ifdef LARGE_INSTRUCTION_CACHE bits1 = bits; @@ -445,43 +643,113 @@ pdst++; } } } +#endif /* (PSZ == 24 && MROP == 0) */ #endif /* DO_UNALIGNED_BITBLT */ + + } } #endif /* ! DO_MEMCPY */ else /* xdir == -1 */ { +#if PSZ == 24 && MROP == 0 + xoffSrc = (-(pptSrc->x + w)) & PAM; + xoffDst = (-pbox->x2) & PAM; +#if 1 + if(xoffSrc != xoffDst /* Alignments must be same. */ + || ((widthDstBytes & PAM) != (widthSrcBytes & PAM) && h > 1)) +#else + if(1) +#endif + /* Width also must be same, if hight > 1 */ + { + /* ...otherwise, pixel by pixel operation */ + while (h--) + { + register int i, si, sii, di; + + for (i = 0, si = pptSrc->x + w - 1, di = pbox->x2 - 1; + i < w; + i++, si--, di--) { + psrc = psrcLine + ((si * BYPP) >> P2WSH); + pdst = pdstLine + ((di * BYPP) >> P2WSH); + sii = (si & PAM); + MROP_SOLID24P(psrc, pdst, sii, di); + } + psrcLine += widthSrc; + pdstLine += widthDst; + } + }else +#endif /* MROP == 0 && PSZ == 24 */ + { + +#if PSZ == 24 +#if MROP == 0 + /* already calculated */ +#else + xoffSrc = (pptSrc->x + w) & PAM; + xoffDst = pbox->x2 & PAM; +#endif + pdstLine += ((pbox->x2 * BYPP - 1) >> P2WSH) + 1; + psrcLine += (((pptSrc->x+w) * BYPP - 1) >> P2WSH) + 1; +#else xoffSrc = (pptSrc->x + w - 1) & PIM; xoffDst = (pbox->x2 - 1) & PIM; pdstLine += ((pbox->x2-1) >> PWSH) + 1; psrcLine += ((pptSrc->x+w - 1) >> PWSH) + 1; +#endif #ifdef DO_UNALIGNED_BITBLT +#if PSZ == 24 + nl = xoffDst - xoffSrc; +#else nl = xoffSrc - xoffDst; - psrcLine = (unsigned long *) +#endif + psrcLine = (CfbBits *) (((unsigned char *) psrcLine) + nl); #else +#if PSZ == 24 && MROP == 0 + /* already satisfied */ +#else if (xoffSrc == xoffDst) #endif +#endif { while (h--) { +#if PSZ == 24 && MROP == 0 + register int index; + register int im3; +#endif /* PSZ == 24 && MROP == 0 */ psrc = psrcLine; pdst = pdstLine; pdstLine += widthDst; psrcLine += widthSrc; +#if PSZ == 24 && MROP == 0 + index = (int)(pdst - pdstBase); +#endif /* PSZ == 24 && MROP == 0 */ + if (endmask) { pdst--; psrc--; +#if PSZ == 24 && MROP == 0 + index--; + im3 = index % 3; + *pdst = DoMaskMergeRop24u(*psrc, *pdst, endmask, im3); +#else /* !(PSZ == 24 && MROP == 0) */ *pdst = MROP_MASK (*psrc, *pdst, endmask); +#endif /* PSZ == 24 && MROP == 0 */ } nl = nlMiddle; - #ifdef LARGE_INSTRUCTION_CACHE #ifdef FAST_CONSTANT_OFFSET_MODE psrc -= nl & (UNROLL - 1); pdst -= nl & (UNROLL - 1); +#if PSZ == 24 && MROP == 0 +#define BodyOdd(n) pdst[n-1] = DoMergeRop24u(psrc[n-1], pdst[n-1], ((int)(pdst - (n - 1) -pdstBase)) % 3); +#else /* !(PSZ == 24 && MROP == 0) */ #define BodyOdd(n) pdst[n-1] = MROP_SOLID (psrc[n-1], pdst[n-1]); +#endif /* PSZ == 24 && MROP == 0 */ #define BodyEven(n) BodyOdd(n) @@ -491,7 +759,11 @@ psrc -= UNROLL; #else +#if PSZ == 24 && MROP == 0 +#define BodyOdd(n) --pdst; --psrc; --index; im3 = index % 3;*pdst = DoMergeRop24u(*psrc, *pdst, im3); +#else /* !(PSZ == 24 && MROP == 0) */ #define BodyOdd(n) --pdst; --psrc; *pdst = MROP_SOLID(*psrc, *pdst); +#endif /* PSZ == 24 && MROP == 0 */ #define BodyEven(n) BodyOdd(n) #define LoopReset ; @@ -503,38 +775,60 @@ psrc -= UNROLL; #undef LoopReset #else +#if PSZ == 24 && MROP == 0 + DuffL(nl,label3, + --pdst; --psrc; --index; im3= index%3;*pdst = DoMergeRop24u(*psrc, *pdst, im3);) +#else /* !(PSZ == 24 && MROP == 0) */ DuffL(nl,label3, --pdst; --psrc; *pdst = MROP_SOLID (*psrc, *pdst);) +#endif /* PSZ == 24 && MROP == 0 */ #endif if (startmask) { --pdst; --psrc; +#if PSZ == 24 && MROP == 0 + *pdst = DoMaskMergeRop24u(*psrc, *pdst, startmask, (int)(pdst - pdstBase) % 3); +#else /* !(PSZ == 24 && MROP == 0) */ *pdst = MROP_MASK(*psrc, *pdst, startmask); +#endif /* PSZ == 24 && MROP == 0 */ } } } #ifndef DO_UNALIGNED_BITBLT +#if PSZ == 24 && MROP == 0 + /* can not happen */ +#else /* !( PSZ == 24 && MROP == 0) */ else { if (xoffDst > xoffSrc) { +#if PSZ == 24 + leftShift = (xoffDst - xoffSrc) << 3; + rightShift = PGSZ - leftShift; +#else #if PGSZ == 32 rightShift = (xoffDst - xoffSrc) << (5 - PWSH); #else /* PGSZ == 64 */ rightShift = (xoffDst - xoffSrc) << (6 - PWSH); #endif /* PGSZ */ leftShift = PGSZ - rightShift; +#endif } else { +#if PSZ == 24 + rightShift = (xoffSrc - xoffDst) << 3; + leftShift = PGSZ - rightShift; +#else #if PGSZ == 32 leftShift = (xoffSrc - xoffDst) << (5 - PWSH); #else /* PGSZ == 64 */ leftShift = (xoffSrc - xoffDst) << (6 - PWSH); #endif /* PGSZ */ rightShift = PGSZ - leftShift; +#endif } while (h--) { @@ -543,7 +837,11 @@ psrc -= UNROLL; pdstLine += widthDst; psrcLine += widthSrc; bits = 0; +#if PSZ == 24 + if (xoffSrc > xoffDst) +#else if (xoffDst > xoffSrc) +#endif bits = *--psrc; if (endmask) { @@ -554,7 +852,6 @@ psrc -= UNROLL; *pdst = MROP_MASK(bits1, *pdst, endmask); } nl = nlMiddle; - #ifdef LARGE_INSTRUCTION_CACHE bits1 = bits; #ifdef FAST_CONSTANT_OFFSET_MODE @@ -615,7 +912,9 @@ bits1 = *--psrc; --pdst; \ } } } +#endif /* PSZ == 24 && MROP == 0 */ #endif + } } pbox++; pptSrc++; |