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 19005b261ecSmrg /* 19105b261ecSmrg * Do not read past the end of the buffer! 19205b261ecSmrg */ 19305b261ecSmrg srcEnd = src + height * srcStride; 19405b261ecSmrg 19505b261ecSmrg /* 19605b261ecSmrg * Number of destination units in FbBits == number of stipple pixels 19705b261ecSmrg * used each time 19805b261ecSmrg */ 19905b261ecSmrg pixelsPerDst = FB_UNIT / dstBpp; 20005b261ecSmrg 20105b261ecSmrg /* 20235c4bbdfSmrg * Number of source stipple patterns in FbStip 20305b261ecSmrg */ 20405b261ecSmrg unitsPerSrc = FB_STIP_UNIT / pixelsPerDst; 20535c4bbdfSmrg 20605b261ecSmrg copy = FALSE; 20705b261ecSmrg transparent = FALSE; 20805b261ecSmrg if (bgand == 0 && fgand == 0) 20935c4bbdfSmrg copy = TRUE; 21005b261ecSmrg else if (bgand == FB_ALLONES && bgxor == 0) 21135c4bbdfSmrg transparent = TRUE; 21205b261ecSmrg 21305b261ecSmrg /* 21405b261ecSmrg * Adjust source and dest to nearest FbBits boundary 21505b261ecSmrg */ 21605b261ecSmrg src += srcX >> FB_STIP_SHIFT; 21705b261ecSmrg dst += dstX >> FB_SHIFT; 21805b261ecSmrg srcX &= FB_STIP_MASK; 21905b261ecSmrg dstX &= FB_MASK; 22005b261ecSmrg 22135c4bbdfSmrg FbMaskBitsBytes(dstX, width, copy, 22235c4bbdfSmrg startmask, startbyte, nmiddle, endmask, endbyte); 22305b261ecSmrg 22405b261ecSmrg /* 22505b261ecSmrg * Compute effective dest alignment requirement for 22605b261ecSmrg * source -- must align source to dest unit boundary 22705b261ecSmrg */ 22805b261ecSmrg dstS = dstX / dstBpp; 22905b261ecSmrg /* 230ed6184dfSmrg * Compute shift constants for effective alignment 23105b261ecSmrg */ 23235c4bbdfSmrg if (srcX >= dstS) { 23335c4bbdfSmrg leftShift = srcX - dstS; 23435c4bbdfSmrg rightShift = FB_STIP_UNIT - leftShift; 23505b261ecSmrg } 23635c4bbdfSmrg else { 23735c4bbdfSmrg rightShift = dstS - srcX; 23835c4bbdfSmrg leftShift = FB_STIP_UNIT - rightShift; 23905b261ecSmrg } 24005b261ecSmrg /* 24105b261ecSmrg * Get pointer to stipple mask array for this depth 24205b261ecSmrg */ 24335c4bbdfSmrg fbBits = 0; /* unused */ 24435c4bbdfSmrg switch (pixelsPerDst) { 24535c4bbdfSmrg case 8: 24635c4bbdfSmrg fbBits = fbStipple8Bits; 24735c4bbdfSmrg break; 24835c4bbdfSmrg case 4: 24935c4bbdfSmrg fbBits = fbStipple4Bits; 25035c4bbdfSmrg break; 25135c4bbdfSmrg case 2: 25235c4bbdfSmrg fbBits = fbStipple2Bits; 25335c4bbdfSmrg break; 25435c4bbdfSmrg case 1: 25535c4bbdfSmrg fbBits = fbStipple1Bits; 25635c4bbdfSmrg break; 25735c4bbdfSmrg default: 25835c4bbdfSmrg return; 25935c4bbdfSmrg } 26035c4bbdfSmrg 26105b261ecSmrg /* 26235c4bbdfSmrg * Compute total number of destination words written, but 26335c4bbdfSmrg * don't count endmask 26405b261ecSmrg */ 26505b261ecSmrg nDst = nmiddle; 26605b261ecSmrg if (startmask) 26735c4bbdfSmrg nDst++; 26835c4bbdfSmrg 26905b261ecSmrg dstStride -= nDst; 27005b261ecSmrg 27105b261ecSmrg /* 27205b261ecSmrg * Compute total number of source words consumed 27305b261ecSmrg */ 27435c4bbdfSmrg 27505b261ecSmrg srcinc = (nDst + unitsPerSrc - 1) / unitsPerSrc; 27635c4bbdfSmrg 27705b261ecSmrg if (srcX > dstS) 27835c4bbdfSmrg srcinc++; 27935c4bbdfSmrg if (endmask) { 28035c4bbdfSmrg endNeedsLoad = nDst % unitsPerSrc == 0; 28135c4bbdfSmrg if (endNeedsLoad) 28235c4bbdfSmrg srcinc++; 28305b261ecSmrg } 28405b261ecSmrg 28505b261ecSmrg srcStride -= srcinc; 28635c4bbdfSmrg 28705b261ecSmrg /* 28805b261ecSmrg * Copy rectangle 28905b261ecSmrg */ 29035c4bbdfSmrg while (height--) { 29135c4bbdfSmrg w = nDst; /* total units across scanline */ 29235c4bbdfSmrg n = unitsPerSrc; /* units avail in single stipple */ 29335c4bbdfSmrg if (n > w) 29435c4bbdfSmrg n = w; 29535c4bbdfSmrg 29635c4bbdfSmrg bitsLeft = 0; 29735c4bbdfSmrg if (srcX > dstS) 29835c4bbdfSmrg bitsLeft = READ(src++); 29935c4bbdfSmrg if (n) { 30035c4bbdfSmrg /* 30135c4bbdfSmrg * Load first set of stipple bits 30235c4bbdfSmrg */ 30335c4bbdfSmrg LoadBits; 30435c4bbdfSmrg 30535c4bbdfSmrg /* 30635c4bbdfSmrg * Consume stipple bits for startmask 30735c4bbdfSmrg */ 30835c4bbdfSmrg if (startmask) { 30935c4bbdfSmrg mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 31035c4bbdfSmrg if (mask || !transparent) 31135c4bbdfSmrg FbDoLeftMaskByteStippleRRop(dst, mask, 31235c4bbdfSmrg fgand, fgxor, bgand, bgxor, 31335c4bbdfSmrg startbyte, startmask); 31435c4bbdfSmrg bits = FbStipLeft(bits, pixelsPerDst); 31535c4bbdfSmrg dst++; 31635c4bbdfSmrg n--; 31735c4bbdfSmrg w--; 31835c4bbdfSmrg } 31935c4bbdfSmrg /* 32035c4bbdfSmrg * Consume stipple bits across scanline 32135c4bbdfSmrg */ 32235c4bbdfSmrg for (;;) { 32335c4bbdfSmrg w -= n; 32435c4bbdfSmrg if (copy) { 32535c4bbdfSmrg while (n--) { 32635c4bbdfSmrg mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 32735c4bbdfSmrg WRITE(dst, FbOpaqueStipple(mask, fgxor, bgxor)); 32835c4bbdfSmrg dst++; 32935c4bbdfSmrg bits = FbStipLeft(bits, pixelsPerDst); 33035c4bbdfSmrg } 33135c4bbdfSmrg } 33235c4bbdfSmrg else { 33335c4bbdfSmrg while (n--) { 33435c4bbdfSmrg left = FbLeftStipBits(bits, pixelsPerDst); 33535c4bbdfSmrg if (left || !transparent) { 33635c4bbdfSmrg mask = fbBits[left]; 33735c4bbdfSmrg WRITE(dst, FbStippleRRop(READ(dst), mask, fgand, 33835c4bbdfSmrg fgxor, bgand, bgxor)); 33935c4bbdfSmrg } 34035c4bbdfSmrg dst++; 34135c4bbdfSmrg bits = FbStipLeft(bits, pixelsPerDst); 34235c4bbdfSmrg } 34335c4bbdfSmrg } 34435c4bbdfSmrg if (!w) 34535c4bbdfSmrg break; 34635c4bbdfSmrg /* 34735c4bbdfSmrg * Load another set and reset number of available units 34835c4bbdfSmrg */ 34935c4bbdfSmrg LoadBits; 35035c4bbdfSmrg n = unitsPerSrc; 35135c4bbdfSmrg if (n > w) 35235c4bbdfSmrg n = w; 35335c4bbdfSmrg } 35435c4bbdfSmrg } 35535c4bbdfSmrg /* 35635c4bbdfSmrg * Consume stipple bits for endmask 35735c4bbdfSmrg */ 35835c4bbdfSmrg if (endmask) { 35935c4bbdfSmrg if (endNeedsLoad) { 36035c4bbdfSmrg LoadBits; 36135c4bbdfSmrg } 36235c4bbdfSmrg mask = fbBits[FbLeftStipBits(bits, pixelsPerDst)]; 36335c4bbdfSmrg if (mask || !transparent) 36435c4bbdfSmrg FbDoRightMaskByteStippleRRop(dst, mask, fgand, fgxor, 36535c4bbdfSmrg bgand, bgxor, endbyte, endmask); 36635c4bbdfSmrg } 36735c4bbdfSmrg dst += dstStride; 36835c4bbdfSmrg src += srcStride; 36905b261ecSmrg } 37005b261ecSmrg} 37105b261ecSmrg 37205b261ecSmrg/* 37305b261ecSmrg * Not very efficient, but simple -- copy a single plane 37405b261ecSmrg * from an N bit image to a 1 bit image 37505b261ecSmrg */ 37635c4bbdfSmrg 37705b261ecSmrgvoid 37835c4bbdfSmrgfbBltPlane(FbBits * src, 37935c4bbdfSmrg FbStride srcStride, 38035c4bbdfSmrg int srcX, 38135c4bbdfSmrg int srcBpp, 38235c4bbdfSmrg FbStip * dst, 38335c4bbdfSmrg FbStride dstStride, 38435c4bbdfSmrg int dstX, 38535c4bbdfSmrg int width, 38635c4bbdfSmrg int height, 38735c4bbdfSmrg FbStip fgand, 38835c4bbdfSmrg FbStip fgxor, FbStip bgand, FbStip bgxor, Pixel planeMask) 38905b261ecSmrg{ 39035c4bbdfSmrg FbBits *s; 39135c4bbdfSmrg FbBits pm; 39235c4bbdfSmrg FbBits srcMask; 39335c4bbdfSmrg FbBits srcMaskFirst; 39435c4bbdfSmrg FbBits srcMask0 = 0; 39535c4bbdfSmrg FbBits srcBits; 39635c4bbdfSmrg 39735c4bbdfSmrg FbStip dstBits; 39835c4bbdfSmrg FbStip *d; 39935c4bbdfSmrg FbStip dstMask; 40035c4bbdfSmrg FbStip dstMaskFirst; 40135c4bbdfSmrg FbStip dstUnion; 40235c4bbdfSmrg int w; 40335c4bbdfSmrg int wt; 40405b261ecSmrg 40505b261ecSmrg if (!width) 40635c4bbdfSmrg return; 40735c4bbdfSmrg 40805b261ecSmrg src += srcX >> FB_SHIFT; 40905b261ecSmrg srcX &= FB_MASK; 41005b261ecSmrg 41105b261ecSmrg dst += dstX >> FB_STIP_SHIFT; 41205b261ecSmrg dstX &= FB_STIP_MASK; 41335c4bbdfSmrg 41405b261ecSmrg w = width / srcBpp; 41505b261ecSmrg 41635c4bbdfSmrg pm = fbReplicatePixel(planeMask, srcBpp); 4171b5d61b8Smrg srcMaskFirst = pm & FbBitsMask(srcX, srcBpp); 4181b5d61b8Smrg srcMask0 = pm & FbBitsMask(0, srcBpp); 41935c4bbdfSmrg 42035c4bbdfSmrg dstMaskFirst = FbStipMask(dstX, 1); 42135c4bbdfSmrg while (height--) { 42235c4bbdfSmrg d = dst; 42335c4bbdfSmrg dst += dstStride; 42435c4bbdfSmrg s = src; 42535c4bbdfSmrg src += srcStride; 42635c4bbdfSmrg 42735c4bbdfSmrg srcMask = srcMaskFirst; 42835c4bbdfSmrg srcBits = READ(s++); 42935c4bbdfSmrg 43035c4bbdfSmrg dstMask = dstMaskFirst; 43135c4bbdfSmrg dstUnion = 0; 43235c4bbdfSmrg dstBits = 0; 43335c4bbdfSmrg 43435c4bbdfSmrg wt = w; 43535c4bbdfSmrg 43635c4bbdfSmrg while (wt--) { 43735c4bbdfSmrg if (!srcMask) { 43835c4bbdfSmrg srcBits = READ(s++); 43935c4bbdfSmrg srcMask = srcMask0; 44035c4bbdfSmrg } 44135c4bbdfSmrg if (!dstMask) { 44235c4bbdfSmrg WRITE(d, FbStippleRRopMask(READ(d), dstBits, 44335c4bbdfSmrg fgand, fgxor, bgand, bgxor, 44435c4bbdfSmrg dstUnion)); 44535c4bbdfSmrg d++; 44635c4bbdfSmrg dstMask = FbStipMask(0, 1); 44735c4bbdfSmrg dstUnion = 0; 44835c4bbdfSmrg dstBits = 0; 44935c4bbdfSmrg } 45035c4bbdfSmrg if (srcBits & srcMask) 45135c4bbdfSmrg dstBits |= dstMask; 45235c4bbdfSmrg dstUnion |= dstMask; 45335c4bbdfSmrg if (srcBpp == FB_UNIT) 45435c4bbdfSmrg srcMask = 0; 45535c4bbdfSmrg else 45635c4bbdfSmrg srcMask = FbScrRight(srcMask, srcBpp); 45735c4bbdfSmrg dstMask = FbStipRight(dstMask, 1); 45835c4bbdfSmrg } 45935c4bbdfSmrg if (dstUnion) 46035c4bbdfSmrg WRITE(d, FbStippleRRopMask(READ(d), dstBits, 46135c4bbdfSmrg fgand, fgxor, bgand, bgxor, dstUnion)); 46205b261ecSmrg } 46305b261ecSmrg} 464