2
* Id: fbbltone.c,v 1.1 1999/11/02 03:54:45 keithp Exp $
4
* Copyright Ā© 1998 Keith Packard
6
* Permission to use, copy, modify, distribute, and sell this software and its
7
* documentation for any purpose is hereby granted without fee, provided that
8
* the above copyright notice appear in all copies and that both that
9
* copyright notice and this permission notice appear in supporting
10
* documentation, and that the name of Keith Packard not be used in
11
* advertising or publicity pertaining to distribution of the software without
12
* specific, written prior permission. Keith Packard makes no
13
* representations about the suitability of this software for any purpose. It
14
* is provided "as is" without express or implied warranty.
16
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
* PERFORMANCE OF THIS SOFTWARE.
24
/* $XFree86: xc/programs/Xserver/fb/fbbltone.c,v 1.11 2001/09/07 15:15:31 keithp Exp $ */
26
#ifdef HAVE_DIX_CONFIG_H
27
#include <dix-config.h>
33
* Example: srcX = 13 dstX = 8 (FB unit 32 dstBpp 8)
35
* **** **** **** **** **** **** **** ****
37
* ******** ******** ******** ********
42
* Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8)
44
* **** **** **** **** **** **** **** ****
46
* ******** ******** ******** ********
55
bitsRight = (src != srcEnd ? *src++ : 0); \
56
bits = (FbStipLeft (bitsLeft, leftShift) | \
57
FbStipRight(bitsRight, rightShift)); \
58
bitsLeft = bitsRight; \
60
bits = (src != srcEnd ? *src++ : 0); \
65
#define LaneCases1(n,a) case n: (void)FbLaneCase(n,a); break
66
#define LaneCases2(n,a) LaneCases1(n,a); LaneCases1(n+1,a)
67
#define LaneCases4(n,a) LaneCases2(n,a); LaneCases2(n+2,a)
68
#define LaneCases8(n,a) LaneCases4(n,a); LaneCases4(n+4,a)
69
#define LaneCases16(n,a) LaneCases8(n,a); LaneCases8(n+8,a)
70
#define LaneCases32(n,a) LaneCases16(n,a); LaneCases16(n+16,a)
71
#define LaneCases64(n,a) LaneCases32(n,a); LaneCases32(n+32,a)
72
#define LaneCases128(n,a) LaneCases64(n,a); LaneCases64(n+64,a)
73
#define LaneCases256(n,a) LaneCases128(n,a); LaneCases128(n+128,a)
76
#define LaneCases(a) LaneCases256(0,a)
80
#define LaneCases(a) LaneCases16(0,a)
84
CARD8 fb8Lane[256] = {
85
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
86
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
87
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
88
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
89
79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
90
98, 99, 100, 101, 102,103,104,105,106,107,108,109,110,111,112,113,114,115,
91
116, 117, 118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,
92
134, 135, 136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,
93
152, 153, 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,
94
170, 171, 172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,
95
188, 189, 190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,
96
206, 207, 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
97
224, 225, 226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,
98
242, 243, 244,245,246,247,248,249,250,251,252,253,254,255,
101
CARD8 fb16Lane[256] = {
102
0x00, 0x03, 0x0c, 0x0f,
103
0x30, 0x33, 0x3c, 0x3f,
104
0xc0, 0xc3, 0xcc, 0xcf,
105
0xf0, 0xf3, 0xfc, 0xff,
108
CARD8 fb32Lane[16] = {
109
0x00, 0x0f, 0xf0, 0xff,
114
CARD8 fb8Lane[16] = {
115
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
118
CARD8 fb16Lane[16] = {
119
0, 3, 12, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
122
CARD8 fb32Lane[16] = {
123
0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
127
CARD8 *fbLaneTable[33] = {
128
0, 0, 0, 0, 0, 0, 0, 0,
129
fb8Lane, 0, 0, 0, 0, 0, 0, 0,
130
fb16Lane, 0, 0, 0, 0, 0, 0, 0,
131
0, 0, 0, 0, 0, 0, 0, 0,
137
fbBltOne (FbStip *src,
138
FbStride srcStride, /* FbStip units per scanline */
139
int srcX, /* bit position of source */
141
FbStride dstStride, /* FbBits units per scanline */
142
int dstX, /* bit position of dest */
143
int dstBpp, /* bits per destination unit */
145
int width, /* width in bits of destination */
146
int height, /* height in scanlines */
148
FbBits fgand, /* rrop values */
153
const FbBits *fbBits;
155
int pixelsPerDst; /* dst pixels per FbBits */
156
int unitsPerSrc; /* src patterns per FbStip */
157
int leftShift, rightShift; /* align source with dest */
158
FbBits startmask, endmask; /* dest scanline masks */
159
FbStip bits=0, bitsLeft, bitsRight;/* source bits */
162
int nDst; /* dest longwords (w.o. end) */
165
int dstS; /* stipple-relative dst X coordinate */
166
Bool copy; /* accelerate dest-invariant */
167
Bool transparent; /* accelerate 0 nop */
168
int srcinc; /* source units consumed */
169
Bool endNeedsLoad = FALSE; /* need load for endmask */
173
int startbyte, endbyte;
178
fbBltOne24 (src, srcStride, srcX,
179
dst, dstStride, dstX, dstBpp,
181
fgand, fgxor, bgand, bgxor);
187
* Do not read past the end of the buffer!
189
srcEnd = src + height * srcStride;
192
* Number of destination units in FbBits == number of stipple pixels
195
pixelsPerDst = FB_UNIT / dstBpp;
198
* Number of source stipple patterns in FbStip
200
unitsPerSrc = FB_STIP_UNIT / pixelsPerDst;
204
if (bgand == 0 && fgand == 0)
206
else if (bgand == FB_ALLONES && bgxor == 0)
210
* Adjust source and dest to nearest FbBits boundary
212
src += srcX >> FB_STIP_SHIFT;
213
dst += dstX >> FB_SHIFT;
214
srcX &= FB_STIP_MASK;
217
FbMaskBitsBytes(dstX, width, copy,
218
startmask, startbyte, nmiddle, endmask, endbyte);
221
* Compute effective dest alignment requirement for
222
* source -- must align source to dest unit boundary
224
dstS = dstX / dstBpp;
226
* Compute shift constants for effective alignement
230
leftShift = srcX - dstS;
231
rightShift = FB_STIP_UNIT - leftShift;
235
rightShift = dstS - srcX;
236
leftShift = FB_STIP_UNIT - rightShift;
239
* Get pointer to stipple mask array for this depth
241
fbBits = 0; /* unused */
242
if (pixelsPerDst <= 8)
243
fbBits = fbStippleTable[pixelsPerDst];
246
if (transparent && fgand == 0 && dstBpp >= 8)
247
fbLane = fbLaneTable[dstBpp];
251
* Compute total number of destination words written, but
252
* don't count endmask
261
* Compute total number of source words consumed
264
srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc;
270
endNeedsLoad = nmiddle % unitsPerSrc == 0;
282
w = nDst; /* total units across scanline */
283
n = unitsPerSrc; /* units avail in single stipple */
293
* Load first set of stipple bits
298
* Consume stipple bits for startmask
303
if (pixelsPerDst == 16)
304
mask = FbStipple16Bits(FbLeftStipBits(bits,16));
307
mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
311
fbTransparentSpan (dst, mask & startmask, fgxor, 1);
316
if (mask || !transparent)
317
FbDoLeftMaskByteStippleRRop (dst, mask,
318
fgand, fgxor, bgand, bgxor,
319
startbyte, startmask);
321
bits = FbStipLeft (bits, pixelsPerDst);
327
* Consume stipple bits across scanline
337
if (pixelsPerDst == 16)
338
mask = FbStipple16Bits(FbLeftStipBits(bits,16));
341
mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
342
*dst = FbOpaqueStipple (mask, fgxor, bgxor);
344
bits = FbStipLeft(bits, pixelsPerDst);
354
switch (fbLane[FbLeftStipBits(bits,pixelsPerDst)]) {
355
LaneCases((CARD8 *) dst);
357
bits = FbStipLeft(bits,pixelsPerDst);
368
left = FbLeftStipBits(bits,pixelsPerDst);
369
if (left || !transparent)
372
*dst = FbStippleRRop (*dst, mask,
373
fgand, fgxor, bgand, bgxor);
376
bits = FbStipLeft(bits, pixelsPerDst);
383
* Load another set and reset number of available units
392
* Consume stipple bits for endmask
401
if (pixelsPerDst == 16)
402
mask = FbStipple16Bits(FbLeftStipBits(bits,16));
405
mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
409
fbTransparentSpan (dst, mask & endmask, fgxor, 1);
414
if (mask || !transparent)
415
FbDoRightMaskByteStippleRRop (dst, mask,
416
fgand, fgxor, bgand, bgxor,
428
* Crufty macros to initialize the mask array, most of this
429
* is to avoid compile-time warnings about shift overflow
432
#if BITMAP_BIT_ORDER == MSBFirst
433
#define Mask24Pos(x,r) ((x)*24-(r))
435
#define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0))
438
#define Mask24Neg(x,r) (Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0)
439
#define Mask24Check(x,r) (Mask24Pos(x,r) < 0 ? 0 : \
440
Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r))
442
#define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \
443
(Mask24Pos(x,r) < 0 ? \
444
0xffffff >> Mask24Neg (x,r) : \
445
0xffffff << Mask24Check(x,r)) : 0)
447
#define SelMask24(b,n,r) ((((b) >> n) & 1) * Mask24(n,r))
450
* Untested for MSBFirst or FB_UNIT == 32
455
(SelMask24(b,0,r) | \
460
#define FbStip24New(rot) (2 + (rot != 0))
461
#define FbStip24Len 4
463
const FbBits fbStipple24Bits[3][1 << FbStip24Len] = {
466
C4_24( 0, 0), C4_24( 1, 0), C4_24( 2, 0), C4_24( 3, 0),
467
C4_24( 4, 0), C4_24( 5, 0), C4_24( 6, 0), C4_24( 7, 0),
468
C4_24( 8, 0), C4_24( 9, 0), C4_24(10, 0), C4_24(11, 0),
469
C4_24(12, 0), C4_24(13, 0), C4_24(14, 0), C4_24(15, 0),
473
C4_24( 0, 8), C4_24( 1, 8), C4_24( 2, 8), C4_24( 3, 8),
474
C4_24( 4, 8), C4_24( 5, 8), C4_24( 6, 8), C4_24( 7, 8),
475
C4_24( 8, 8), C4_24( 9, 8), C4_24(10, 8), C4_24(11, 8),
476
C4_24(12, 8), C4_24(13, 8), C4_24(14, 8), C4_24(15, 8),
480
C4_24( 0,16), C4_24( 1,16), C4_24( 2,16), C4_24( 3,16),
481
C4_24( 4,16), C4_24( 5,16), C4_24( 6,16), C4_24( 7,16),
482
C4_24( 8,16), C4_24( 9,16), C4_24(10,16), C4_24(11,16),
483
C4_24(12,16), C4_24(13,16), C4_24(14,16), C4_24(15,16),
491
(SelMask24(b,0,r) | \
494
#define FbStip24Len 2
495
#if BITMAP_BIT_ORDER == MSBFirst
496
#define FbStip24New(rot) (1 + (rot == 0))
498
#define FbStip24New(rot) (1 + (rot == 8))
501
const FbBits fbStipple24Bits[3][1 << FbStip24Len] = {
504
C2_24( 0, 0), C2_24 ( 1, 0), C2_24 ( 2, 0), C2_24 ( 3, 0),
508
C2_24( 0, 8), C2_24 ( 1, 8), C2_24 ( 2, 8), C2_24 ( 3, 8),
512
C2_24( 0,16), C2_24 ( 1,16), C2_24 ( 2,16), C2_24 ( 3,16),
517
#if BITMAP_BIT_ORDER == LSBFirst
519
#define FbMergeStip24Bits(left, right, new) \
520
(FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new))))
522
#define FbMergePartStip24Bits(left, right, llen, rlen) \
523
(left | FbStipRight(right, llen))
527
#define FbMergeStip24Bits(left, right, new) \
528
((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right)
530
#define FbMergePartStip24Bits(left, right, llen, rlen) \
531
(FbStipLeft(left, rlen) | right)
535
#define fbFirstStipBits(len,stip) {\
537
if (len <= remain) { \
538
stip = FbLeftStipBits(bits, len); \
540
stip = FbLeftStipBits(bits, remain); \
541
bits = (src != srcEnd ? *src++ : 0); \
542
__len = (len) - remain; \
543
stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \
545
remain = FB_STIP_UNIT; \
547
bits = FbStipLeft (bits, __len); \
551
#define fbInitStipBits(offset,len,stip) {\
552
bits = FbStipLeft (*src++,offset); \
553
remain = FB_STIP_UNIT - offset; \
554
fbFirstStipBits(len,stip); \
555
stip = FbMergeStip24Bits (0, stip, len); \
558
#define fbNextStipBits(rot,stip) {\
559
int __new = FbStip24New(rot); \
561
fbFirstStipBits(__new, __right); \
562
stip = FbMergeStip24Bits (stip, __right, __new); \
563
rot = FbNext24Rot (rot); \
567
* Use deep mask tables that incorporate rotation, pull
568
* a variable number of bits out of the stipple and
569
* reuse the right bits as needed for the next write
571
* Yes, this is probably too much code, but most 24-bpp screens
572
* have no acceleration so this code is used for stipples, copyplane
576
fbBltOne24 (FbStip *srcLine,
577
FbStride srcStride, /* FbStip units per scanline */
578
int srcX, /* bit position of source */
580
FbStride dstStride, /* FbBits units per scanline */
581
int dstX, /* bit position of dest */
582
int dstBpp, /* bits per destination unit */
584
int width, /* width in bits of destination */
585
int height, /* height in scanlines */
587
FbBits fgand, /* rrop values */
592
FbStip *src, *srcEnd;
593
FbBits leftMask, rightMask, mask;
603
* Do not read past the end of the buffer!
605
srcEnd = srcLine + height * srcStride;
607
srcLine += srcX >> FB_STIP_SHIFT;
608
dst += dstX >> FB_SHIFT;
609
srcX &= FB_STIP_MASK;
611
rot0 = FbFirst24Rot (dstX);
613
FbMaskBits (dstX, width, leftMask, nlMiddle, rightMask);
615
dstS = (dstX + 23) / 24;
616
firstlen = FbStip24Len - dstS;
624
if (bgand == 0 && fgand == 0)
630
srcLine += srcStride;
631
fbInitStipBits (srcX,firstlen, stip);
634
mask = fbStipple24Bits[rot >> 3][stip];
635
*dst = (*dst & ~leftMask) | (FbOpaqueStipple (mask,
640
fbNextStipBits(rot,stip);
645
mask = fbStipple24Bits[rot>>3][stip];
646
*dst = FbOpaqueStipple (mask,
648
FbRot24(bgxor, rot));
650
fbNextStipBits(rot,stip);
654
mask = fbStipple24Bits[rot >> 3][stip];
655
*dst = (*dst & ~rightMask) | (FbOpaqueStipple (mask,
664
/* transparent copy */
665
else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0)
671
srcLine += srcStride;
672
fbInitStipBits (srcX, firstlen, stip);
677
mask = fbStipple24Bits[rot >> 3][stip] & leftMask;
678
*dst = (*dst & ~mask) | (FbRot24(fgxor, rot) & mask);
681
fbNextStipBits (rot, stip);
688
mask = fbStipple24Bits[rot>>3][stip];
689
*dst = (*dst & ~mask) | (FbRot24(fgxor,rot) & mask);
692
fbNextStipBits (rot, stip);
698
mask = fbStipple24Bits[rot >> 3][stip] & rightMask;
699
*dst = (*dst & ~mask) | (FbRot24(fgxor, rot) & mask);
711
srcLine += srcStride;
712
fbInitStipBits (srcX, firstlen, stip);
715
mask = fbStipple24Bits[rot >> 3][stip];
716
*dst = FbStippleRRopMask (*dst, mask,
723
fbNextStipBits(rot,stip);
728
mask = fbStipple24Bits[rot >> 3][stip];
729
*dst = FbStippleRRop (*dst, mask,
733
FbRot24(bgxor, rot));
735
fbNextStipBits(rot,stip);
739
mask = fbStipple24Bits[rot >> 3][stip];
740
*dst = FbStippleRRopMask (*dst, mask,
754
* Not very efficient, but simple -- copy a single plane
755
* from an N bit image to a 1 bit image
759
fbBltPlane (FbBits *src,
796
src += srcX >> FB_SHIFT;
799
dst += dstX >> FB_STIP_SHIFT;
800
dstX &= FB_STIP_MASK;
804
pm = fbReplicatePixel (planeMask, srcBpp);
810
rot0 = FbFirst24Rot (srcX);
811
if (srcX + w > FB_UNIT)
813
srcMaskFirst = FbRot24(pm,rot0) & FbBitsMask(srcX,w);
819
srcMaskFirst = pm & FbBitsMask(srcX, srcBpp);
820
srcMask0 = pm & FbBitsMask(0, srcBpp);
823
dstMaskFirst = FbStipMask(dstX,1);
831
srcMask = srcMaskFirst;
834
srcMask0 = FbRot24(pm,rot0) & FbBitsMask(0, srcBpp);
838
dstMask = dstMaskFirst;
851
srcMask0 = FbNext24Pix(srcMask0) & FbBitsMask(0,24);
857
*d = FbStippleRRopMask(*d, dstBits,
858
fgand, fgxor, bgand, bgxor,
861
dstMask = FbStipMask(0,1);
865
if (srcBits & srcMask)
868
if (srcBpp == FB_UNIT)
871
srcMask = FbScrRight(srcMask,srcBpp);
872
dstMask = FbStipRight(dstMask,1);
875
*d = FbStippleRRopMask(*d,dstBits,
876
fgand, fgxor, bgand, bgxor,