fbbltone.c revision 35c4bbdf
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 2935c4bbdfSmrg/* 3035c4bbdfSmrg * Stipple masks are independent of bit/byte order as long 3135c4bbdfSmrg * as bitorder == byteorder. FB doesn't handle the case 3235c4bbdfSmrg * where these differ 3335c4bbdfSmrg */ 3435c4bbdfSmrg#define BitsMask(x,w) ((FB_ALLONES << ((x) & FB_MASK)) & \ 3535c4bbdfSmrg (FB_ALLONES >> ((FB_UNIT - ((x) + (w))) & FB_MASK))) 3635c4bbdfSmrg 3735c4bbdfSmrg#define Mask(x,w) BitsMask((x)*(w),(w)) 3835c4bbdfSmrg 3935c4bbdfSmrg#define SelMask(b,n,w) ((((b) >> n) & 1) * Mask(n,w)) 4035c4bbdfSmrg 4135c4bbdfSmrg#define C1(b,w) \ 4235c4bbdfSmrg (SelMask(b,0,w)) 4335c4bbdfSmrg 4435c4bbdfSmrg#define C2(b,w) \ 4535c4bbdfSmrg (SelMask(b,0,w) | \ 4635c4bbdfSmrg SelMask(b,1,w)) 4735c4bbdfSmrg 4835c4bbdfSmrg#define C4(b,w) \ 4935c4bbdfSmrg (SelMask(b,0,w) | \ 5035c4bbdfSmrg SelMask(b,1,w) | \ 5135c4bbdfSmrg SelMask(b,2,w) | \ 5235c4bbdfSmrg SelMask(b,3,w)) 5335c4bbdfSmrg 5435c4bbdfSmrg#define C8(b,w) \ 5535c4bbdfSmrg (SelMask(b,0,w) | \ 5635c4bbdfSmrg SelMask(b,1,w) | \ 5735c4bbdfSmrg SelMask(b,2,w) | \ 5835c4bbdfSmrg SelMask(b,3,w) | \ 5935c4bbdfSmrg SelMask(b,4,w) | \ 6035c4bbdfSmrg SelMask(b,5,w) | \ 6135c4bbdfSmrg SelMask(b,6,w) | \ 6235c4bbdfSmrg SelMask(b,7,w)) 6335c4bbdfSmrg 6435c4bbdfSmrgstatic const FbBits fbStipple8Bits[256] = { 6535c4bbdfSmrg C8(0, 4), C8(1, 4), C8(2, 4), C8(3, 4), C8(4, 4), C8(5, 4), 6635c4bbdfSmrg C8(6, 4), C8(7, 4), C8(8, 4), C8(9, 4), C8(10, 4), C8(11, 4), 6735c4bbdfSmrg C8(12, 4), C8(13, 4), C8(14, 4), C8(15, 4), C8(16, 4), C8(17, 4), 6835c4bbdfSmrg C8(18, 4), C8(19, 4), C8(20, 4), C8(21, 4), C8(22, 4), C8(23, 4), 6935c4bbdfSmrg C8(24, 4), C8(25, 4), C8(26, 4), C8(27, 4), C8(28, 4), C8(29, 4), 7035c4bbdfSmrg C8(30, 4), C8(31, 4), C8(32, 4), C8(33, 4), C8(34, 4), C8(35, 4), 7135c4bbdfSmrg C8(36, 4), C8(37, 4), C8(38, 4), C8(39, 4), C8(40, 4), C8(41, 4), 7235c4bbdfSmrg C8(42, 4), C8(43, 4), C8(44, 4), C8(45, 4), C8(46, 4), C8(47, 4), 7335c4bbdfSmrg C8(48, 4), C8(49, 4), C8(50, 4), C8(51, 4), C8(52, 4), C8(53, 4), 7435c4bbdfSmrg C8(54, 4), C8(55, 4), C8(56, 4), C8(57, 4), C8(58, 4), C8(59, 4), 7535c4bbdfSmrg C8(60, 4), C8(61, 4), C8(62, 4), C8(63, 4), C8(64, 4), C8(65, 4), 7635c4bbdfSmrg C8(66, 4), C8(67, 4), C8(68, 4), C8(69, 4), C8(70, 4), C8(71, 4), 7735c4bbdfSmrg C8(72, 4), C8(73, 4), C8(74, 4), C8(75, 4), C8(76, 4), C8(77, 4), 7835c4bbdfSmrg C8(78, 4), C8(79, 4), C8(80, 4), C8(81, 4), C8(82, 4), C8(83, 4), 7935c4bbdfSmrg C8(84, 4), C8(85, 4), C8(86, 4), C8(87, 4), C8(88, 4), C8(89, 4), 8035c4bbdfSmrg C8(90, 4), C8(91, 4), C8(92, 4), C8(93, 4), C8(94, 4), C8(95, 4), 8135c4bbdfSmrg C8(96, 4), C8(97, 4), C8(98, 4), C8(99, 4), C8(100, 4), C8(101, 4), 8235c4bbdfSmrg C8(102, 4), C8(103, 4), C8(104, 4), C8(105, 4), C8(106, 4), C8(107, 4), 8335c4bbdfSmrg C8(108, 4), C8(109, 4), C8(110, 4), C8(111, 4), C8(112, 4), C8(113, 4), 8435c4bbdfSmrg C8(114, 4), C8(115, 4), C8(116, 4), C8(117, 4), C8(118, 4), C8(119, 4), 8535c4bbdfSmrg C8(120, 4), C8(121, 4), C8(122, 4), C8(123, 4), C8(124, 4), C8(125, 4), 8635c4bbdfSmrg C8(126, 4), C8(127, 4), C8(128, 4), C8(129, 4), C8(130, 4), C8(131, 4), 8735c4bbdfSmrg C8(132, 4), C8(133, 4), C8(134, 4), C8(135, 4), C8(136, 4), C8(137, 4), 8835c4bbdfSmrg C8(138, 4), C8(139, 4), C8(140, 4), C8(141, 4), C8(142, 4), C8(143, 4), 8935c4bbdfSmrg C8(144, 4), C8(145, 4), C8(146, 4), C8(147, 4), C8(148, 4), C8(149, 4), 9035c4bbdfSmrg C8(150, 4), C8(151, 4), C8(152, 4), C8(153, 4), C8(154, 4), C8(155, 4), 9135c4bbdfSmrg C8(156, 4), C8(157, 4), C8(158, 4), C8(159, 4), C8(160, 4), C8(161, 4), 9235c4bbdfSmrg C8(162, 4), C8(163, 4), C8(164, 4), C8(165, 4), C8(166, 4), C8(167, 4), 9335c4bbdfSmrg C8(168, 4), C8(169, 4), C8(170, 4), C8(171, 4), C8(172, 4), C8(173, 4), 9435c4bbdfSmrg C8(174, 4), C8(175, 4), C8(176, 4), C8(177, 4), C8(178, 4), C8(179, 4), 9535c4bbdfSmrg C8(180, 4), C8(181, 4), C8(182, 4), C8(183, 4), C8(184, 4), C8(185, 4), 9635c4bbdfSmrg C8(186, 4), C8(187, 4), C8(188, 4), C8(189, 4), C8(190, 4), C8(191, 4), 9735c4bbdfSmrg C8(192, 4), C8(193, 4), C8(194, 4), C8(195, 4), C8(196, 4), C8(197, 4), 9835c4bbdfSmrg C8(198, 4), C8(199, 4), C8(200, 4), C8(201, 4), C8(202, 4), C8(203, 4), 9935c4bbdfSmrg C8(204, 4), C8(205, 4), C8(206, 4), C8(207, 4), C8(208, 4), C8(209, 4), 10035c4bbdfSmrg C8(210, 4), C8(211, 4), C8(212, 4), C8(213, 4), C8(214, 4), C8(215, 4), 10135c4bbdfSmrg C8(216, 4), C8(217, 4), C8(218, 4), C8(219, 4), C8(220, 4), C8(221, 4), 10235c4bbdfSmrg C8(222, 4), C8(223, 4), C8(224, 4), C8(225, 4), C8(226, 4), C8(227, 4), 10335c4bbdfSmrg C8(228, 4), C8(229, 4), C8(230, 4), C8(231, 4), C8(232, 4), C8(233, 4), 10435c4bbdfSmrg C8(234, 4), C8(235, 4), C8(236, 4), C8(237, 4), C8(238, 4), C8(239, 4), 10535c4bbdfSmrg C8(240, 4), C8(241, 4), C8(242, 4), C8(243, 4), C8(244, 4), C8(245, 4), 10635c4bbdfSmrg C8(246, 4), C8(247, 4), C8(248, 4), C8(249, 4), C8(250, 4), C8(251, 4), 10735c4bbdfSmrg C8(252, 4), C8(253, 4), C8(254, 4), C8(255, 4), 10835c4bbdfSmrg}; 10935c4bbdfSmrg 11035c4bbdfSmrgstatic const FbBits fbStipple4Bits[16] = { 11135c4bbdfSmrg C4(0, 8), C4(1, 8), C4(2, 8), C4(3, 8), C4(4, 8), C4(5, 8), 11235c4bbdfSmrg C4(6, 8), C4(7, 8), C4(8, 8), C4(9, 8), C4(10, 8), C4(11, 8), 11335c4bbdfSmrg C4(12, 8), C4(13, 8), C4(14, 8), C4(15, 8), 11435c4bbdfSmrg}; 11535c4bbdfSmrg 11635c4bbdfSmrgstatic const FbBits fbStipple2Bits[4] = { 11735c4bbdfSmrg C2(0, 16), C2(1, 16), C2(2, 16), C2(3, 16), 11835c4bbdfSmrg}; 11935c4bbdfSmrg 12035c4bbdfSmrgstatic const FbBits fbStipple1Bits[2] = { 12135c4bbdfSmrg C1(0, 32), C1(1, 32), 12235c4bbdfSmrg}; 12335c4bbdfSmrg 12435c4bbdfSmrg#ifdef __clang__ 12535c4bbdfSmrg/* shift overflow is intentional */ 12635c4bbdfSmrg#pragma clang diagnostic ignored "-Wshift-overflow" 12735c4bbdfSmrg#endif 12835c4bbdfSmrg 12905b261ecSmrg/* 13005b261ecSmrg * Example: srcX = 13 dstX = 8 (FB unit 32 dstBpp 8) 13105b261ecSmrg * 13205b261ecSmrg * **** **** **** **** **** **** **** **** 13305b261ecSmrg * ^ 13405b261ecSmrg * ******** ******** ******** ******** 13505b261ecSmrg * ^ 13605b261ecSmrg * leftShift = 12 13705b261ecSmrg * rightShift = 20 13805b261ecSmrg * 13905b261ecSmrg * Example: srcX = 0 dstX = 8 (FB unit 32 dstBpp 8) 14005b261ecSmrg * 14105b261ecSmrg * **** **** **** **** **** **** **** **** 14205b261ecSmrg * ^ 14305b261ecSmrg * ******** ******** ******** ******** 14405b261ecSmrg * ^ 14505b261ecSmrg * 14605b261ecSmrg * leftShift = 24 14705b261ecSmrg * rightShift = 8 14805b261ecSmrg */ 14905b261ecSmrg 15005b261ecSmrg#define LoadBits {\ 15105b261ecSmrg if (leftShift) { \ 15205b261ecSmrg bitsRight = (src < srcEnd ? READ(src++) : 0); \ 15305b261ecSmrg bits = (FbStipLeft (bitsLeft, leftShift) | \ 15405b261ecSmrg FbStipRight(bitsRight, rightShift)); \ 15505b261ecSmrg bitsLeft = bitsRight; \ 15605b261ecSmrg } else \ 15705b261ecSmrg bits = (src < srcEnd ? READ(src++) : 0); \ 15805b261ecSmrg} 15905b261ecSmrg 16005b261ecSmrgvoid 16135c4bbdfSmrgfbBltOne(FbStip * src, FbStride srcStride, /* FbStip units per scanline */ 16235c4bbdfSmrg int srcX, /* bit position of source */ 16335c4bbdfSmrg FbBits * dst, FbStride dstStride, /* FbBits units per scanline */ 16435c4bbdfSmrg int dstX, /* bit position of dest */ 16535c4bbdfSmrg int dstBpp, /* bits per destination unit */ 16635c4bbdfSmrg int width, /* width in bits of destination */ 16735c4bbdfSmrg int height, /* height in scanlines */ 16835c4bbdfSmrg FbBits fgand, /* rrop values */ 16935c4bbdfSmrg FbBits fgxor, FbBits bgand, FbBits bgxor) 17005b261ecSmrg{ 17135c4bbdfSmrg const FbBits *fbBits; 17235c4bbdfSmrg FbBits *srcEnd; 17335c4bbdfSmrg int pixelsPerDst; /* dst pixels per FbBits */ 17435c4bbdfSmrg int unitsPerSrc; /* src patterns per FbStip */ 17535c4bbdfSmrg int leftShift, rightShift; /* align source with dest */ 17635c4bbdfSmrg FbBits startmask, endmask; /* dest scanline masks */ 17735c4bbdfSmrg FbStip bits = 0, bitsLeft, bitsRight; /* source bits */ 17835c4bbdfSmrg FbStip left; 17935c4bbdfSmrg FbBits mask; 18035c4bbdfSmrg int nDst; /* dest longwords (w.o. end) */ 18135c4bbdfSmrg int w; 18235c4bbdfSmrg int n, nmiddle; 18335c4bbdfSmrg int dstS; /* stipple-relative dst X coordinate */ 18435c4bbdfSmrg Bool copy; /* accelerate dest-invariant */ 18535c4bbdfSmrg Bool transparent; /* accelerate 0 nop */ 18635c4bbdfSmrg int srcinc; /* source units consumed */ 18735c4bbdfSmrg Bool endNeedsLoad = FALSE; /* need load for endmask */ 18835c4bbdfSmrg int startbyte, endbyte; 18935c4bbdfSmrg 19035c4bbdfSmrg if (dstBpp == 24) { 19135c4bbdfSmrg fbBltOne24(src, srcStride, srcX, 19235c4bbdfSmrg dst, dstStride, dstX, dstBpp, 19335c4bbdfSmrg width, height, fgand, fgxor, bgand, bgxor); 19435c4bbdfSmrg return; 19505b261ecSmrg } 19605b261ecSmrg 19705b261ecSmrg /* 19805b261ecSmrg * Do not read past the end of the buffer! 19905b261ecSmrg */ 20005b261ecSmrg srcEnd = src + height * srcStride; 20105b261ecSmrg 20205b261ecSmrg /* 20305b261ecSmrg * Number of destination units in FbBits == number of stipple pixels 20405b261ecSmrg * used each time 20505b261ecSmrg */ 20605b261ecSmrg pixelsPerDst = FB_UNIT / dstBpp; 20705b261ecSmrg 20805b261ecSmrg /* 20935c4bbdfSmrg * Number of source stipple patterns in FbStip 21005b261ecSmrg */ 21105b261ecSmrg unitsPerSrc = FB_STIP_UNIT / pixelsPerDst; 21235c4bbdfSmrg 21305b261ecSmrg copy = FALSE; 21405b261ecSmrg transparent = FALSE; 21505b261ecSmrg if (bgand == 0 && fgand == 0) 21635c4bbdfSmrg copy = TRUE; 21705b261ecSmrg else if (bgand == FB_ALLONES && bgxor == 0) 21835c4bbdfSmrg transparent = TRUE; 21905b261ecSmrg 22005b261ecSmrg /* 22105b261ecSmrg * Adjust source and dest to nearest FbBits boundary 22205b261ecSmrg */ 22305b261ecSmrg src += srcX >> FB_STIP_SHIFT; 22405b261ecSmrg dst += dstX >> FB_SHIFT; 22505b261ecSmrg srcX &= FB_STIP_MASK; 22605b261ecSmrg dstX &= FB_MASK; 22705b261ecSmrg 22835c4bbdfSmrg FbMaskBitsBytes(dstX, width, copy, 22935c4bbdfSmrg startmask, startbyte, nmiddle, endmask, endbyte); 23005b261ecSmrg 23105b261ecSmrg /* 23205b261ecSmrg * Compute effective dest alignment requirement for 23305b261ecSmrg * source -- must align source to dest unit boundary 23405b261ecSmrg */ 23505b261ecSmrg dstS = dstX / dstBpp; 23605b261ecSmrg /* 23705b261ecSmrg * Compute shift constants for effective alignement 23805b261ecSmrg */ 23935c4bbdfSmrg if (srcX >= dstS) { 24035c4bbdfSmrg leftShift = srcX - dstS; 24135c4bbdfSmrg rightShift = FB_STIP_UNIT - leftShift; 24205b261ecSmrg } 24335c4bbdfSmrg else { 24435c4bbdfSmrg rightShift = dstS - srcX; 24535c4bbdfSmrg leftShift = FB_STIP_UNIT - rightShift; 24605b261ecSmrg } 24705b261ecSmrg /* 24805b261ecSmrg * Get pointer to stipple mask array for this depth 24905b261ecSmrg */ 25035c4bbdfSmrg fbBits = 0; /* unused */ 25135c4bbdfSmrg switch (pixelsPerDst) { 25235c4bbdfSmrg case 8: 25335c4bbdfSmrg fbBits = fbStipple8Bits; 25435c4bbdfSmrg break; 25535c4bbdfSmrg case 4: 25635c4bbdfSmrg fbBits = fbStipple4Bits; 25735c4bbdfSmrg break; 25835c4bbdfSmrg case 2: 25935c4bbdfSmrg fbBits = fbStipple2Bits; 26035c4bbdfSmrg break; 26135c4bbdfSmrg case 1: 26235c4bbdfSmrg fbBits = fbStipple1Bits; 26335c4bbdfSmrg break; 26435c4bbdfSmrg default: 26535c4bbdfSmrg return; 26635c4bbdfSmrg } 26735c4bbdfSmrg 26805b261ecSmrg /* 26935c4bbdfSmrg * Compute total number of destination words written, but 27035c4bbdfSmrg * don't count endmask 27105b261ecSmrg */ 27205b261ecSmrg nDst = nmiddle; 27305b261ecSmrg if (startmask) 27435c4bbdfSmrg nDst++; 27535c4bbdfSmrg 27605b261ecSmrg dstStride -= nDst; 27705b261ecSmrg 27805b261ecSmrg /* 27905b261ecSmrg * Compute total number of source words consumed 28005b261ecSmrg */ 28135c4bbdfSmrg 28205b261ecSmrg srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc; 28335c4bbdfSmrg 28405b261ecSmrg if (srcX > dstS) 28535c4bbdfSmrg srcinc++; 28635c4bbdfSmrg if (endmask) { 28735c4bbdfSmrg endNeedsLoad = nDst % unitsPerSrc == 0; 28835c4bbdfSmrg if (endNeedsLoad) 28935c4bbdfSmrg srcinc++; 29005b261ecSmrg } 29105b261ecSmrg 29205b261ecSmrg srcStride -= srcinc; 29335c4bbdfSmrg 29405b261ecSmrg /* 29505b261ecSmrg * Copy rectangle 29605b261ecSmrg */ 29735c4bbdfSmrg while (height--) { 29835c4bbdfSmrg w = nDst; /* total units across scanline */ 29935c4bbdfSmrg n = unitsPerSrc; /* units avail in single stipple */ 30035c4bbdfSmrg if (n > w) 30135c4bbdfSmrg n = w; 30235c4bbdfSmrg 30335c4bbdfSmrg bitsLeft = 0; 30435c4bbdfSmrg if (srcX > dstS) 30535c4bbdfSmrg bitsLeft = READ(src++); 30635c4bbdfSmrg if (n) { 30735c4bbdfSmrg /* 30835c4bbdfSmrg * Load first set of stipple bits 30935c4bbdfSmrg */ 31035c4bbdfSmrg LoadBits; 31135c4bbdfSmrg 31235c4bbdfSmrg /* 31335c4bbdfSmrg * Consume stipple bits for startmask 31435c4bbdfSmrg */ 31535c4bbdfSmrg if (startmask) { 31635c4bbdfSmrg mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 31735c4bbdfSmrg if (mask || !transparent) 31835c4bbdfSmrg FbDoLeftMaskByteStippleRRop(dst, mask, 31935c4bbdfSmrg fgand, fgxor, bgand, bgxor, 32035c4bbdfSmrg startbyte, startmask); 32135c4bbdfSmrg bits = FbStipLeft(bits, pixelsPerDst); 32235c4bbdfSmrg dst++; 32335c4bbdfSmrg n--; 32435c4bbdfSmrg w--; 32535c4bbdfSmrg } 32635c4bbdfSmrg /* 32735c4bbdfSmrg * Consume stipple bits across scanline 32835c4bbdfSmrg */ 32935c4bbdfSmrg for (;;) { 33035c4bbdfSmrg w -= n; 33135c4bbdfSmrg if (copy) { 33235c4bbdfSmrg while (n--) { 33335c4bbdfSmrg mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 33435c4bbdfSmrg WRITE(dst, FbOpaqueStipple(mask, fgxor, bgxor)); 33535c4bbdfSmrg dst++; 33635c4bbdfSmrg bits = FbStipLeft(bits, pixelsPerDst); 33735c4bbdfSmrg } 33835c4bbdfSmrg } 33935c4bbdfSmrg else { 34035c4bbdfSmrg while (n--) { 34135c4bbdfSmrg left = FbLeftStipBits(bits, pixelsPerDst); 34235c4bbdfSmrg if (left || !transparent) { 34335c4bbdfSmrg mask = fbBits[left]; 34435c4bbdfSmrg WRITE(dst, FbStippleRRop(READ(dst), mask, fgand, 34535c4bbdfSmrg fgxor, bgand, bgxor)); 34635c4bbdfSmrg } 34735c4bbdfSmrg dst++; 34835c4bbdfSmrg bits = FbStipLeft(bits, pixelsPerDst); 34935c4bbdfSmrg } 35035c4bbdfSmrg } 35135c4bbdfSmrg if (!w) 35235c4bbdfSmrg break; 35335c4bbdfSmrg /* 35435c4bbdfSmrg * Load another set and reset number of available units 35535c4bbdfSmrg */ 35635c4bbdfSmrg LoadBits; 35735c4bbdfSmrg n = unitsPerSrc; 35835c4bbdfSmrg if (n > w) 35935c4bbdfSmrg n = w; 36035c4bbdfSmrg } 36135c4bbdfSmrg } 36235c4bbdfSmrg /* 36335c4bbdfSmrg * Consume stipple bits for endmask 36435c4bbdfSmrg */ 36535c4bbdfSmrg if (endmask) { 36635c4bbdfSmrg if (endNeedsLoad) { 36735c4bbdfSmrg LoadBits; 36835c4bbdfSmrg } 36935c4bbdfSmrg mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 37035c4bbdfSmrg if (mask || !transparent) 37135c4bbdfSmrg FbDoRightMaskByteStippleRRop(dst, mask, fgand, fgxor, 37235c4bbdfSmrg bgand, bgxor, endbyte, endmask); 37335c4bbdfSmrg } 37435c4bbdfSmrg dst += dstStride; 37535c4bbdfSmrg src += srcStride; 37605b261ecSmrg } 37705b261ecSmrg} 37805b261ecSmrg 37905b261ecSmrg/* 38005b261ecSmrg * Crufty macros to initialize the mask array, most of this 38105b261ecSmrg * is to avoid compile-time warnings about shift overflow 38205b261ecSmrg */ 38305b261ecSmrg 38405b261ecSmrg#if BITMAP_BIT_ORDER == MSBFirst 38505b261ecSmrg#define Mask24Pos(x,r) ((x)*24-(r)) 38605b261ecSmrg#else 38705b261ecSmrg#define Mask24Pos(x,r) ((x)*24-((r) ? 24 - (r) : 0)) 38805b261ecSmrg#endif 38905b261ecSmrg 39005b261ecSmrg#define Mask24Neg(x,r) (Mask24Pos(x,r) < 0 ? -Mask24Pos(x,r) : 0) 39105b261ecSmrg#define Mask24Check(x,r) (Mask24Pos(x,r) < 0 ? 0 : \ 39205b261ecSmrg Mask24Pos(x,r) >= FB_UNIT ? 0 : Mask24Pos(x,r)) 39305b261ecSmrg 39405b261ecSmrg#define Mask24(x,r) (Mask24Pos(x,r) < FB_UNIT ? \ 39505b261ecSmrg (Mask24Pos(x,r) < 0 ? \ 3969ace9065Smrg 0xffffffU >> Mask24Neg (x,r) : \ 3979ace9065Smrg 0xffffffU << Mask24Check(x,r)) : 0) 39805b261ecSmrg 39905b261ecSmrg#define SelMask24(b,n,r) ((((b) >> n) & 1) * Mask24(n,r)) 40005b261ecSmrg 40105b261ecSmrg#define C2_24(b,r) \ 40205b261ecSmrg (SelMask24(b,0,r) | \ 40305b261ecSmrg SelMask24(b,1,r)) 40405b261ecSmrg 40505b261ecSmrg#define FbStip24Len 2 40605b261ecSmrg#if BITMAP_BIT_ORDER == MSBFirst 40705b261ecSmrg#define FbStip24New(rot) (1 + (rot == 0)) 40805b261ecSmrg#else 40905b261ecSmrg#define FbStip24New(rot) (1 + (rot == 8)) 41005b261ecSmrg#endif 41105b261ecSmrg 41235c4bbdfSmrgconst FbBits fbStipple24Bits[3][1 << FbStip24Len] = { 41305b261ecSmrg /* rotate 0 */ 41405b261ecSmrg { 41535c4bbdfSmrg C2_24(0, 0), C2_24(1, 0), C2_24(2, 0), C2_24(3, 0), 41635c4bbdfSmrg }, 41705b261ecSmrg /* rotate 8 */ 41805b261ecSmrg { 41935c4bbdfSmrg C2_24(0, 8), C2_24(1, 8), C2_24(2, 8), C2_24(3, 8), 42035c4bbdfSmrg }, 42105b261ecSmrg /* rotate 16 */ 42205b261ecSmrg { 42335c4bbdfSmrg C2_24(0, 16), C2_24(1, 16), C2_24(2, 16), C2_24(3, 16), 42435c4bbdfSmrg } 42505b261ecSmrg}; 42605b261ecSmrg 42705b261ecSmrg#if BITMAP_BIT_ORDER == LSBFirst 42805b261ecSmrg 42905b261ecSmrg#define FbMergeStip24Bits(left, right, new) \ 43005b261ecSmrg (FbStipLeft (left, new) | FbStipRight ((right), (FbStip24Len - (new)))) 43105b261ecSmrg 43205b261ecSmrg#define FbMergePartStip24Bits(left, right, llen, rlen) \ 43305b261ecSmrg (left | FbStipRight(right, llen)) 43405b261ecSmrg 43505b261ecSmrg#else 43605b261ecSmrg 43705b261ecSmrg#define FbMergeStip24Bits(left, right, new) \ 43805b261ecSmrg ((FbStipLeft (left, new) & ((1 << FbStip24Len) - 1)) | right) 43905b261ecSmrg 44005b261ecSmrg#define FbMergePartStip24Bits(left, right, llen, rlen) \ 44105b261ecSmrg (FbStipLeft(left, rlen) | right) 44205b261ecSmrg 44305b261ecSmrg#endif 44405b261ecSmrg 44505b261ecSmrg#define fbFirstStipBits(len,stip) {\ 44605b261ecSmrg int __len = (len); \ 44705b261ecSmrg if (len <= remain) { \ 44805b261ecSmrg stip = FbLeftStipBits(bits, len); \ 44905b261ecSmrg } else { \ 45005b261ecSmrg stip = FbLeftStipBits(bits, remain); \ 45105b261ecSmrg bits = (src < srcEnd ? READ(src++) : 0); \ 45205b261ecSmrg __len = (len) - remain; \ 45305b261ecSmrg stip = FbMergePartStip24Bits(stip, FbLeftStipBits(bits, __len), \ 45405b261ecSmrg remain, __len); \ 45505b261ecSmrg remain = FB_STIP_UNIT; \ 45605b261ecSmrg } \ 45705b261ecSmrg bits = FbStipLeft (bits, __len); \ 45805b261ecSmrg remain -= __len; \ 45905b261ecSmrg} 46005b261ecSmrg 46105b261ecSmrg#define fbInitStipBits(offset,len,stip) {\ 46205b261ecSmrg bits = FbStipLeft (READ(src++),offset); \ 46305b261ecSmrg remain = FB_STIP_UNIT - offset; \ 46405b261ecSmrg fbFirstStipBits(len,stip); \ 46505b261ecSmrg stip = FbMergeStip24Bits (0, stip, len); \ 46605b261ecSmrg} 46735c4bbdfSmrg 46805b261ecSmrg#define fbNextStipBits(rot,stip) {\ 46905b261ecSmrg int __new = FbStip24New(rot); \ 47005b261ecSmrg FbStip __right; \ 47105b261ecSmrg fbFirstStipBits(__new, __right); \ 47205b261ecSmrg stip = FbMergeStip24Bits (stip, __right, __new); \ 47305b261ecSmrg rot = FbNext24Rot (rot); \ 47405b261ecSmrg} 47505b261ecSmrg 47605b261ecSmrg/* 47705b261ecSmrg * Use deep mask tables that incorporate rotation, pull 47805b261ecSmrg * a variable number of bits out of the stipple and 47905b261ecSmrg * reuse the right bits as needed for the next write 48005b261ecSmrg * 48105b261ecSmrg * Yes, this is probably too much code, but most 24-bpp screens 48205b261ecSmrg * have no acceleration so this code is used for stipples, copyplane 48305b261ecSmrg * and text 48405b261ecSmrg */ 48505b261ecSmrgvoid 48635c4bbdfSmrgfbBltOne24(FbStip * srcLine, FbStride srcStride, /* FbStip units per scanline */ 48735c4bbdfSmrg int srcX, /* bit position of source */ 48835c4bbdfSmrg FbBits * dst, FbStride dstStride, /* FbBits units per scanline */ 48935c4bbdfSmrg int dstX, /* bit position of dest */ 49035c4bbdfSmrg int dstBpp, /* bits per destination unit */ 49135c4bbdfSmrg int width, /* width in bits of destination */ 49235c4bbdfSmrg int height, /* height in scanlines */ 49335c4bbdfSmrg FbBits fgand, /* rrop values */ 49435c4bbdfSmrg FbBits fgxor, FbBits bgand, FbBits bgxor) 49505b261ecSmrg{ 49635c4bbdfSmrg FbStip *src, *srcEnd; 49735c4bbdfSmrg FbBits leftMask, rightMask, mask; 49835c4bbdfSmrg int nlMiddle, nl; 49935c4bbdfSmrg FbStip stip, bits; 50035c4bbdfSmrg int remain; 50135c4bbdfSmrg int dstS; 50235c4bbdfSmrg int firstlen; 50335c4bbdfSmrg int rot0, rot; 50435c4bbdfSmrg int nDst; 50535c4bbdfSmrg 50605b261ecSmrg /* 50705b261ecSmrg * Do not read past the end of the buffer! 50805b261ecSmrg */ 50905b261ecSmrg srcEnd = srcLine + height * srcStride; 51005b261ecSmrg 51105b261ecSmrg srcLine += srcX >> FB_STIP_SHIFT; 51205b261ecSmrg dst += dstX >> FB_SHIFT; 51305b261ecSmrg srcX &= FB_STIP_MASK; 51405b261ecSmrg dstX &= FB_MASK; 51535c4bbdfSmrg rot0 = FbFirst24Rot(dstX); 51635c4bbdfSmrg 51735c4bbdfSmrg FbMaskBits(dstX, width, leftMask, nlMiddle, rightMask); 51835c4bbdfSmrg 51905b261ecSmrg dstS = (dstX + 23) / 24; 52005b261ecSmrg firstlen = FbStip24Len - dstS; 52135c4bbdfSmrg 52205b261ecSmrg nDst = nlMiddle; 52305b261ecSmrg if (leftMask) 52435c4bbdfSmrg nDst++; 52505b261ecSmrg dstStride -= nDst; 52635c4bbdfSmrg 52705b261ecSmrg /* opaque copy */ 52835c4bbdfSmrg if (bgand == 0 && fgand == 0) { 52935c4bbdfSmrg while (height--) { 53035c4bbdfSmrg rot = rot0; 53135c4bbdfSmrg src = srcLine; 53235c4bbdfSmrg srcLine += srcStride; 53335c4bbdfSmrg fbInitStipBits(srcX, firstlen, stip); 53435c4bbdfSmrg if (leftMask) { 53535c4bbdfSmrg mask = fbStipple24Bits[rot >> 3][stip]; 53635c4bbdfSmrg WRITE(dst, (READ(dst) & ~leftMask) | 53735c4bbdfSmrg (FbOpaqueStipple(mask, 53835c4bbdfSmrg FbRot24(fgxor, rot), FbRot24(bgxor, rot)) 53935c4bbdfSmrg & leftMask)); 54035c4bbdfSmrg dst++; 54135c4bbdfSmrg fbNextStipBits(rot, stip); 54235c4bbdfSmrg } 54335c4bbdfSmrg nl = nlMiddle; 54435c4bbdfSmrg while (nl--) { 54535c4bbdfSmrg mask = fbStipple24Bits[rot >> 3][stip]; 54635c4bbdfSmrg WRITE(dst, FbOpaqueStipple(mask, 54735c4bbdfSmrg FbRot24(fgxor, rot), 54835c4bbdfSmrg FbRot24(bgxor, rot))); 54935c4bbdfSmrg dst++; 55035c4bbdfSmrg fbNextStipBits(rot, stip); 55135c4bbdfSmrg } 55235c4bbdfSmrg if (rightMask) { 55335c4bbdfSmrg mask = fbStipple24Bits[rot >> 3][stip]; 55435c4bbdfSmrg WRITE(dst, (READ(dst) & ~rightMask) | 55535c4bbdfSmrg (FbOpaqueStipple(mask, 55635c4bbdfSmrg FbRot24(fgxor, rot), FbRot24(bgxor, rot)) 55735c4bbdfSmrg & rightMask)); 55835c4bbdfSmrg } 55935c4bbdfSmrg dst += dstStride; 56035c4bbdfSmrg src += srcStride; 56135c4bbdfSmrg } 56205b261ecSmrg } 56305b261ecSmrg /* transparent copy */ 56435c4bbdfSmrg else if (bgand == FB_ALLONES && bgxor == 0 && fgand == 0) { 56535c4bbdfSmrg while (height--) { 56635c4bbdfSmrg rot = rot0; 56735c4bbdfSmrg src = srcLine; 56835c4bbdfSmrg srcLine += srcStride; 56935c4bbdfSmrg fbInitStipBits(srcX, firstlen, stip); 57035c4bbdfSmrg if (leftMask) { 57135c4bbdfSmrg if (stip) { 57235c4bbdfSmrg mask = fbStipple24Bits[rot >> 3][stip] & leftMask; 57335c4bbdfSmrg WRITE(dst, 57435c4bbdfSmrg (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 57535c4bbdfSmrg } 57635c4bbdfSmrg dst++; 57735c4bbdfSmrg fbNextStipBits(rot, stip); 57835c4bbdfSmrg } 57935c4bbdfSmrg nl = nlMiddle; 58035c4bbdfSmrg while (nl--) { 58135c4bbdfSmrg if (stip) { 58235c4bbdfSmrg mask = fbStipple24Bits[rot >> 3][stip]; 58335c4bbdfSmrg WRITE(dst, 58435c4bbdfSmrg (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 58535c4bbdfSmrg } 58635c4bbdfSmrg dst++; 58735c4bbdfSmrg fbNextStipBits(rot, stip); 58835c4bbdfSmrg } 58935c4bbdfSmrg if (rightMask) { 59035c4bbdfSmrg if (stip) { 59135c4bbdfSmrg mask = fbStipple24Bits[rot >> 3][stip] & rightMask; 59235c4bbdfSmrg WRITE(dst, 59335c4bbdfSmrg (READ(dst) & ~mask) | (FbRot24(fgxor, rot) & mask)); 59435c4bbdfSmrg } 59535c4bbdfSmrg } 59635c4bbdfSmrg dst += dstStride; 59735c4bbdfSmrg } 59805b261ecSmrg } 59935c4bbdfSmrg else { 60035c4bbdfSmrg while (height--) { 60135c4bbdfSmrg rot = rot0; 60235c4bbdfSmrg src = srcLine; 60335c4bbdfSmrg srcLine += srcStride; 60435c4bbdfSmrg fbInitStipBits(srcX, firstlen, stip); 60535c4bbdfSmrg if (leftMask) { 60635c4bbdfSmrg mask = fbStipple24Bits[rot >> 3][stip]; 60735c4bbdfSmrg WRITE(dst, FbStippleRRopMask(READ(dst), mask, 60835c4bbdfSmrg FbRot24(fgand, rot), 60935c4bbdfSmrg FbRot24(fgxor, rot), 61035c4bbdfSmrg FbRot24(bgand, rot), 61135c4bbdfSmrg FbRot24(bgxor, rot), leftMask)); 61235c4bbdfSmrg dst++; 61335c4bbdfSmrg fbNextStipBits(rot, stip); 61435c4bbdfSmrg } 61535c4bbdfSmrg nl = nlMiddle; 61635c4bbdfSmrg while (nl--) { 61735c4bbdfSmrg mask = fbStipple24Bits[rot >> 3][stip]; 61835c4bbdfSmrg WRITE(dst, FbStippleRRop(READ(dst), mask, 61935c4bbdfSmrg FbRot24(fgand, rot), 62035c4bbdfSmrg FbRot24(fgxor, rot), 62135c4bbdfSmrg FbRot24(bgand, rot), 62235c4bbdfSmrg FbRot24(bgxor, rot))); 62335c4bbdfSmrg dst++; 62435c4bbdfSmrg fbNextStipBits(rot, stip); 62535c4bbdfSmrg } 62635c4bbdfSmrg if (rightMask) { 62735c4bbdfSmrg mask = fbStipple24Bits[rot >> 3][stip]; 62835c4bbdfSmrg WRITE(dst, FbStippleRRopMask(READ(dst), mask, 62935c4bbdfSmrg FbRot24(fgand, rot), 63035c4bbdfSmrg FbRot24(fgxor, rot), 63135c4bbdfSmrg FbRot24(bgand, rot), 63235c4bbdfSmrg FbRot24(bgxor, rot), rightMask)); 63335c4bbdfSmrg } 63435c4bbdfSmrg dst += dstStride; 63535c4bbdfSmrg } 63605b261ecSmrg } 63705b261ecSmrg} 63805b261ecSmrg 63905b261ecSmrg/* 64005b261ecSmrg * Not very efficient, but simple -- copy a single plane 64105b261ecSmrg * from an N bit image to a 1 bit image 64205b261ecSmrg */ 64335c4bbdfSmrg 64405b261ecSmrgvoid 64535c4bbdfSmrgfbBltPlane(FbBits * src, 64635c4bbdfSmrg FbStride srcStride, 64735c4bbdfSmrg int srcX, 64835c4bbdfSmrg int srcBpp, 64935c4bbdfSmrg FbStip * dst, 65035c4bbdfSmrg FbStride dstStride, 65135c4bbdfSmrg int dstX, 65235c4bbdfSmrg int width, 65335c4bbdfSmrg int height, 65435c4bbdfSmrg FbStip fgand, 65535c4bbdfSmrg FbStip fgxor, FbStip bgand, FbStip bgxor, Pixel planeMask) 65605b261ecSmrg{ 65735c4bbdfSmrg FbBits *s; 65835c4bbdfSmrg FbBits pm; 65935c4bbdfSmrg FbBits srcMask; 66035c4bbdfSmrg FbBits srcMaskFirst; 66135c4bbdfSmrg FbBits srcMask0 = 0; 66235c4bbdfSmrg FbBits srcBits; 66335c4bbdfSmrg 66435c4bbdfSmrg FbStip dstBits; 66535c4bbdfSmrg FbStip *d; 66635c4bbdfSmrg FbStip dstMask; 66735c4bbdfSmrg FbStip dstMaskFirst; 66835c4bbdfSmrg FbStip dstUnion; 66935c4bbdfSmrg int w; 67035c4bbdfSmrg int wt; 67135c4bbdfSmrg int rot0; 67205b261ecSmrg 67305b261ecSmrg if (!width) 67435c4bbdfSmrg return; 67535c4bbdfSmrg 67605b261ecSmrg src += srcX >> FB_SHIFT; 67705b261ecSmrg srcX &= FB_MASK; 67805b261ecSmrg 67905b261ecSmrg dst += dstX >> FB_STIP_SHIFT; 68005b261ecSmrg dstX &= FB_STIP_MASK; 68135c4bbdfSmrg 68205b261ecSmrg w = width / srcBpp; 68305b261ecSmrg 68435c4bbdfSmrg pm = fbReplicatePixel(planeMask, srcBpp); 68535c4bbdfSmrg if (srcBpp == 24) { 68635c4bbdfSmrg int tmpw = 24; 68705b261ecSmrg 68835c4bbdfSmrg rot0 = FbFirst24Rot(srcX); 68935c4bbdfSmrg if (srcX + tmpw > FB_UNIT) 69035c4bbdfSmrg tmpw = FB_UNIT - srcX; 69135c4bbdfSmrg srcMaskFirst = FbRot24(pm, rot0) & FbBitsMask(srcX, tmpw); 69205b261ecSmrg } 69335c4bbdfSmrg else { 69435c4bbdfSmrg rot0 = 0; 69535c4bbdfSmrg srcMaskFirst = pm & FbBitsMask(srcX, srcBpp); 69635c4bbdfSmrg srcMask0 = pm & FbBitsMask(0, srcBpp); 69705b261ecSmrg } 69835c4bbdfSmrg 69935c4bbdfSmrg dstMaskFirst = FbStipMask(dstX, 1); 70035c4bbdfSmrg while (height--) { 70135c4bbdfSmrg d = dst; 70235c4bbdfSmrg dst += dstStride; 70335c4bbdfSmrg s = src; 70435c4bbdfSmrg src += srcStride; 70535c4bbdfSmrg 70635c4bbdfSmrg srcMask = srcMaskFirst; 70735c4bbdfSmrg if (srcBpp == 24) 70835c4bbdfSmrg srcMask0 = FbRot24(pm, rot0) & FbBitsMask(0, srcBpp); 70935c4bbdfSmrg srcBits = READ(s++); 71035c4bbdfSmrg 71135c4bbdfSmrg dstMask = dstMaskFirst; 71235c4bbdfSmrg dstUnion = 0; 71335c4bbdfSmrg dstBits = 0; 71435c4bbdfSmrg 71535c4bbdfSmrg wt = w; 71635c4bbdfSmrg 71735c4bbdfSmrg while (wt--) { 71835c4bbdfSmrg if (!srcMask) { 71935c4bbdfSmrg srcBits = READ(s++); 72035c4bbdfSmrg if (srcBpp == 24) 72135c4bbdfSmrg srcMask0 = FbNext24Pix(srcMask0) & FbBitsMask(0, 24); 72235c4bbdfSmrg srcMask = srcMask0; 72335c4bbdfSmrg } 72435c4bbdfSmrg if (!dstMask) { 72535c4bbdfSmrg WRITE(d, FbStippleRRopMask(READ(d), dstBits, 72635c4bbdfSmrg fgand, fgxor, bgand, bgxor, 72735c4bbdfSmrg dstUnion)); 72835c4bbdfSmrg d++; 72935c4bbdfSmrg dstMask = FbStipMask(0, 1); 73035c4bbdfSmrg dstUnion = 0; 73135c4bbdfSmrg dstBits = 0; 73235c4bbdfSmrg } 73335c4bbdfSmrg if (srcBits & srcMask) 73435c4bbdfSmrg dstBits |= dstMask; 73535c4bbdfSmrg dstUnion |= dstMask; 73635c4bbdfSmrg if (srcBpp == FB_UNIT) 73735c4bbdfSmrg srcMask = 0; 73835c4bbdfSmrg else 73935c4bbdfSmrg srcMask = FbScrRight(srcMask, srcBpp); 74035c4bbdfSmrg dstMask = FbStipRight(dstMask, 1); 74135c4bbdfSmrg } 74235c4bbdfSmrg if (dstUnion) 74335c4bbdfSmrg WRITE(d, FbStippleRRopMask(READ(d), dstBits, 74435c4bbdfSmrg fgand, fgxor, bgand, bgxor, dstUnion)); 74505b261ecSmrg } 74605b261ecSmrg} 747