fbblt.c revision 05b261ec
1/*
2 * Copyright © 1998 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Keith Packard makes no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_DIX_CONFIG_H
24#include <dix-config.h>
25#endif
26
27#include <string.h>
28#include "fb.h"
29
30#define InitializeShifts(sx,dx,ls,rs) { \
31    if (sx != dx) { \
32	if (sx > dx) { \
33	    ls = sx - dx; \
34	    rs = FB_UNIT - ls; \
35	} else { \
36	    rs = dx - sx; \
37	    ls = FB_UNIT - rs; \
38	} \
39    } \
40}
41
42void
43fbBlt (FbBits   *srcLine,
44       FbStride	srcStride,
45       int	srcX,
46
47       FbBits   *dstLine,
48       FbStride dstStride,
49       int	dstX,
50
51       int	width,
52       int	height,
53
54       int	alu,
55       FbBits	pm,
56       int	bpp,
57
58       Bool	reverse,
59       Bool	upsidedown)
60{
61    FbBits  *src, *dst;
62    int	    leftShift, rightShift;
63    FbBits  startmask, endmask;
64    FbBits  bits, bits1;
65    int	    n, nmiddle;
66    Bool    destInvarient;
67    int	    startbyte, endbyte;
68    FbDeclareMergeRop ();
69
70#ifdef FB_24BIT
71    if (bpp == 24 && !FbCheck24Pix (pm))
72    {
73	fbBlt24 (srcLine, srcStride, srcX, dstLine, dstStride, dstX,
74		 width, height, alu, pm, reverse, upsidedown);
75	return;
76    }
77#endif
78
79    if (alu == GXcopy && pm == FB_ALLONES && !reverse &&
80            !(srcX & 7) && !(dstX & 7) && !(width & 7)) {
81        int i;
82        CARD8 *src = (CARD8 *) srcLine;
83        CARD8 *dst = (CARD8 *) dstLine;
84
85        srcStride *= sizeof(FbBits);
86        dstStride *= sizeof(FbBits);
87        width >>= 3;
88        src += (srcX >> 3);
89        dst += (dstX >> 3);
90
91        if (!upsidedown)
92            for (i = 0; i < height; i++)
93                MEMCPY_WRAPPED(dst + i * dstStride, src + i * srcStride, width);
94        else
95            for (i = height - 1; i >= 0; i--)
96                MEMCPY_WRAPPED(dst + i * dstStride, src + i * srcStride, width);
97
98        return;
99    }
100
101    FbInitializeMergeRop(alu, pm);
102    destInvarient = FbDestInvarientMergeRop();
103    if (upsidedown)
104    {
105	srcLine += (height - 1) * (srcStride);
106	dstLine += (height - 1) * (dstStride);
107	srcStride = -srcStride;
108	dstStride = -dstStride;
109    }
110    FbMaskBitsBytes (dstX, width, destInvarient, startmask, startbyte,
111		     nmiddle, endmask, endbyte);
112    if (reverse)
113    {
114	srcLine += ((srcX + width - 1) >> FB_SHIFT) + 1;
115	dstLine += ((dstX + width - 1) >> FB_SHIFT) + 1;
116	srcX = (srcX + width - 1) & FB_MASK;
117	dstX = (dstX + width - 1) & FB_MASK;
118    }
119    else
120    {
121	srcLine += srcX >> FB_SHIFT;
122	dstLine += dstX >> FB_SHIFT;
123	srcX &= FB_MASK;
124	dstX &= FB_MASK;
125    }
126    if (srcX == dstX)
127    {
128	while (height--)
129	{
130	    src = srcLine;
131	    srcLine += srcStride;
132	    dst = dstLine;
133	    dstLine += dstStride;
134	    if (reverse)
135	    {
136		if (endmask)
137		{
138		    bits = READ(--src);
139		    --dst;
140		    FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
141		}
142		n = nmiddle;
143		if (destInvarient)
144		{
145		    while (n--)
146			WRITE(--dst, FbDoDestInvarientMergeRop(READ(--src)));
147		}
148		else
149		{
150		    while (n--)
151		    {
152			bits = READ(--src);
153			--dst;
154			WRITE(dst, FbDoMergeRop (bits, READ(dst)));
155		    }
156		}
157		if (startmask)
158		{
159		    bits = READ(--src);
160		    --dst;
161		    FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
162		}
163	    }
164	    else
165	    {
166		if (startmask)
167		{
168		    bits = READ(src++);
169		    FbDoLeftMaskByteMergeRop(dst, bits, startbyte, startmask);
170		    dst++;
171		}
172		n = nmiddle;
173		if (destInvarient)
174		{
175#if 0
176		    /*
177		     * This provides some speedup on screen->screen blts
178		     * over the PCI bus, usually about 10%.  But fb
179		     * isn't usually used for this operation...
180		     */
181		    if (_ca2 + 1 == 0 && _cx2 == 0)
182		    {
183			FbBits	t1, t2, t3, t4;
184			while (n >= 4)
185			{
186			    t1 = *src++;
187			    t2 = *src++;
188			    t3 = *src++;
189			    t4 = *src++;
190			    *dst++ = t1;
191			    *dst++ = t2;
192			    *dst++ = t3;
193			    *dst++ = t4;
194			    n -= 4;
195			}
196		    }
197#endif
198		    while (n--)
199			WRITE(dst++, FbDoDestInvarientMergeRop(READ(src++)));
200		}
201		else
202		{
203		    while (n--)
204		    {
205			bits = READ(src++);
206			WRITE(dst, FbDoMergeRop (bits, READ(dst)));
207			dst++;
208		    }
209		}
210		if (endmask)
211		{
212		    bits = READ(src);
213		    FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
214		}
215	    }
216	}
217    }
218    else
219    {
220	if (srcX > dstX)
221	{
222	    leftShift = srcX - dstX;
223	    rightShift = FB_UNIT - leftShift;
224	}
225	else
226	{
227	    rightShift = dstX - srcX;
228	    leftShift = FB_UNIT - rightShift;
229	}
230	while (height--)
231	{
232	    src = srcLine;
233	    srcLine += srcStride;
234	    dst = dstLine;
235	    dstLine += dstStride;
236
237	    bits1 = 0;
238	    if (reverse)
239	    {
240		if (srcX < dstX)
241		    bits1 = READ(--src);
242		if (endmask)
243		{
244		    bits = FbScrRight(bits1, rightShift);
245		    if (FbScrRight(endmask, leftShift))
246		    {
247			bits1 = READ(--src);
248			bits |= FbScrLeft(bits1, leftShift);
249		    }
250		    --dst;
251		    FbDoRightMaskByteMergeRop(dst, bits, endbyte, endmask);
252		}
253		n = nmiddle;
254		if (destInvarient)
255		{
256		    while (n--)
257		    {
258			bits = FbScrRight(bits1, rightShift);
259			bits1 = READ(--src);
260			bits |= FbScrLeft(bits1, leftShift);
261			--dst;
262			WRITE(dst, FbDoDestInvarientMergeRop(bits));
263		    }
264		}
265		else
266		{
267		    while (n--)
268		    {
269			bits = FbScrRight(bits1, rightShift);
270			bits1 = READ(--src);
271			bits |= FbScrLeft(bits1, leftShift);
272			--dst;
273			WRITE(dst, FbDoMergeRop(bits, READ(dst)));
274		    }
275		}
276		if (startmask)
277		{
278		    bits = FbScrRight(bits1, rightShift);
279		    if (FbScrRight(startmask, leftShift))
280		    {
281			bits1 = READ(--src);
282			bits |= FbScrLeft(bits1, leftShift);
283		    }
284		    --dst;
285		    FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask);
286		}
287	    }
288	    else
289	    {
290		if (srcX > dstX)
291		    bits1 = READ(src++);
292		if (startmask)
293		{
294		    bits = FbScrLeft(bits1, leftShift);
295		    if (FbScrLeft(startmask, rightShift))
296		    {
297			bits1 = READ(src++);
298			bits |= FbScrRight(bits1, rightShift);
299		    }
300		    FbDoLeftMaskByteMergeRop (dst, bits, startbyte, startmask);
301		    dst++;
302		}
303		n = nmiddle;
304		if (destInvarient)
305		{
306		    while (n--)
307		    {
308			bits = FbScrLeft(bits1, leftShift);
309			bits1 = READ(src++);
310			bits |= FbScrRight(bits1, rightShift);
311			WRITE(dst, FbDoDestInvarientMergeRop(bits));
312			dst++;
313		    }
314		}
315		else
316		{
317		    while (n--)
318		    {
319			bits = FbScrLeft(bits1, leftShift);
320			bits1 = READ(src++);
321			bits |= FbScrRight(bits1, rightShift);
322			WRITE(dst, FbDoMergeRop(bits, READ(dst)));
323			dst++;
324		    }
325		}
326		if (endmask)
327		{
328		    bits = FbScrLeft(bits1, leftShift);
329		    if (FbScrLeft(endmask, rightShift))
330		    {
331			bits1 = READ(src);
332			bits |= FbScrRight(bits1, rightShift);
333		    }
334		    FbDoRightMaskByteMergeRop (dst, bits, endbyte, endmask);
335		}
336	    }
337	}
338    }
339}
340
341#ifdef FB_24BIT
342
343#undef DEBUG_BLT24
344#ifdef DEBUG_BLT24
345
346static unsigned long
347getPixel (char *src, int x)
348{
349    unsigned long   l;
350
351    l = 0;
352    memcpy (&l, src + x * 3, 3);
353    return l;
354}
355#endif
356
357static void
358fbBlt24Line (FbBits	    *src,
359	     int	    srcX,
360
361	     FbBits	    *dst,
362	     int	    dstX,
363
364	     int	    width,
365
366	     int	    alu,
367	     FbBits	    pm,
368
369	     Bool	    reverse)
370{
371#ifdef DEBUG_BLT24
372    char    *origDst = (char *) dst;
373    FbBits  *origLine = dst + ((dstX >> FB_SHIFT) - 1);
374    int	    origNlw = ((width + FB_MASK) >> FB_SHIFT) + 3;
375    int	    origX = dstX / 24;
376#endif
377
378    int	    leftShift, rightShift;
379    FbBits  startmask, endmask;
380    int	    n;
381
382    FbBits  bits, bits1;
383    FbBits  mask;
384
385    int	    rot;
386    FbDeclareMergeRop ();
387
388    FbInitializeMergeRop (alu, FB_ALLONES);
389    FbMaskBits(dstX, width, startmask, n, endmask);
390#ifdef DEBUG_BLT24
391    ErrorF ("dstX %d width %d reverse %d\n", dstX, width, reverse);
392#endif
393    if (reverse)
394    {
395	src += ((srcX + width - 1) >> FB_SHIFT) + 1;
396	dst += ((dstX + width - 1) >> FB_SHIFT) + 1;
397	rot = FbFirst24Rot (((dstX + width - 8) & FB_MASK));
398	rot = FbPrev24Rot(rot);
399#ifdef DEBUG_BLT24
400	ErrorF ("dstX + width - 8: %d rot: %d\n", (dstX + width - 8) & FB_MASK, rot);
401#endif
402	srcX = (srcX + width - 1) & FB_MASK;
403	dstX = (dstX + width - 1) & FB_MASK;
404    }
405    else
406    {
407	src += srcX >> FB_SHIFT;
408	dst += dstX >> FB_SHIFT;
409	srcX &= FB_MASK;
410	dstX &= FB_MASK;
411	rot = FbFirst24Rot (dstX);
412#ifdef DEBUG_BLT24
413	ErrorF ("dstX: %d rot: %d\n", dstX, rot);
414#endif
415    }
416    mask = FbRot24(pm,rot);
417#ifdef DEBUG_BLT24
418    ErrorF ("pm 0x%x mask 0x%x\n", pm, mask);
419#endif
420    if (srcX == dstX)
421    {
422	if (reverse)
423	{
424	    if (endmask)
425	    {
426		bits = READ(--src);
427		--dst;
428		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & endmask));
429		mask = FbPrev24Pix (mask);
430	    }
431	    while (n--)
432	    {
433		bits = READ(--src);
434		--dst;
435		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask));
436		mask = FbPrev24Pix (mask);
437	    }
438	    if (startmask)
439	    {
440		bits = READ(--src);
441		--dst;
442		WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & startmask));
443	    }
444	}
445	else
446	{
447	    if (startmask)
448	    {
449		bits = READ(src++);
450		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & startmask));
451		dst++;
452		mask = FbNext24Pix(mask);
453	    }
454	    while (n--)
455	    {
456		bits = READ(src++);
457		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask));
458		dst++;
459		mask = FbNext24Pix(mask);
460	    }
461	    if (endmask)
462	    {
463		bits = READ(src);
464		WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask & endmask));
465	    }
466	}
467    }
468    else
469    {
470	if (srcX > dstX)
471	{
472	    leftShift = srcX - dstX;
473	    rightShift = FB_UNIT - leftShift;
474	}
475	else
476	{
477	    rightShift = dstX - srcX;
478	    leftShift = FB_UNIT - rightShift;
479	}
480
481	bits1 = 0;
482	if (reverse)
483	{
484	    if (srcX < dstX)
485		bits1 = READ(--src);
486	    if (endmask)
487	    {
488		bits = FbScrRight(bits1, rightShift);
489		if (FbScrRight(endmask, leftShift))
490		{
491		    bits1 = READ(--src);
492		    bits |= FbScrLeft(bits1, leftShift);
493		}
494		--dst;
495		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & endmask));
496		mask = FbPrev24Pix(mask);
497	    }
498	    while (n--)
499	    {
500		bits = FbScrRight(bits1, rightShift);
501		bits1 = READ(--src);
502		bits |= FbScrLeft(bits1, leftShift);
503		--dst;
504		WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask));
505		mask = FbPrev24Pix(mask);
506	    }
507	    if (startmask)
508	    {
509		bits = FbScrRight(bits1, rightShift);
510		if (FbScrRight(startmask, leftShift))
511		{
512		    bits1 = READ(--src);
513		    bits |= FbScrLeft(bits1, leftShift);
514		}
515		--dst;
516		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & startmask));
517	    }
518	}
519	else
520	{
521	    if (srcX > dstX)
522		bits1 = READ(src++);
523	    if (startmask)
524	    {
525		bits = FbScrLeft(bits1, leftShift);
526		bits1 = READ(src++);
527		bits |= FbScrRight(bits1, rightShift);
528		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & startmask));
529		dst++;
530		mask = FbNext24Pix(mask);
531	    }
532	    while (n--)
533	    {
534		bits = FbScrLeft(bits1, leftShift);
535		bits1 = READ(src++);
536		bits |= FbScrRight(bits1, rightShift);
537		WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), mask));
538		dst++;
539		mask = FbNext24Pix(mask);
540	    }
541	    if (endmask)
542	    {
543		bits = FbScrLeft(bits1, leftShift);
544		if (FbScrLeft(endmask, rightShift))
545		{
546		    bits1 = READ(src);
547		    bits |= FbScrRight(bits1, rightShift);
548		}
549		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), mask & endmask));
550	    }
551	}
552    }
553#ifdef DEBUG_BLT24
554    {
555	int firstx, lastx, x;
556
557	firstx = origX;
558	if (firstx)
559	    firstx--;
560	lastx = origX + width/24 + 1;
561	for (x = firstx; x <= lastx; x++)
562	    ErrorF ("%06x ", getPixel (origDst, x));
563	ErrorF ("\n");
564	while (origNlw--)
565	    ErrorF ("%08x ", *origLine++);
566	ErrorF ("\n");
567    }
568#endif
569}
570
571void
572fbBlt24 (FbBits	    *srcLine,
573	 FbStride   srcStride,
574	 int	    srcX,
575
576	 FbBits	    *dstLine,
577	 FbStride   dstStride,
578	 int	    dstX,
579
580	 int	    width,
581	 int	    height,
582
583	 int	    alu,
584	 FbBits	    pm,
585
586	 Bool	    reverse,
587	 Bool	    upsidedown)
588{
589    if (upsidedown)
590    {
591	srcLine += (height-1) * srcStride;
592	dstLine += (height-1) * dstStride;
593	srcStride = -srcStride;
594	dstStride = -dstStride;
595    }
596    while (height--)
597    {
598	fbBlt24Line (srcLine, srcX, dstLine, dstX, width, alu, pm, reverse);
599	srcLine += srcStride;
600	dstLine += dstStride;
601    }
602#ifdef DEBUG_BLT24
603    ErrorF ("\n");
604#endif
605}
606#endif /* FB_24BIT */
607
608#if FB_SHIFT == FB_STIP_SHIFT + 1
609
610/*
611 * Could be generalized to FB_SHIFT > FB_STIP_SHIFT + 1 by
612 * creating an ring of values stepped through for each line
613 */
614
615void
616fbBltOdd (FbBits    *srcLine,
617	  FbStride  srcStrideEven,
618	  FbStride  srcStrideOdd,
619	  int	    srcXEven,
620	  int	    srcXOdd,
621
622	  FbBits    *dstLine,
623	  FbStride  dstStrideEven,
624	  FbStride  dstStrideOdd,
625	  int	    dstXEven,
626	  int	    dstXOdd,
627
628	  int	    width,
629	  int	    height,
630
631	  int	    alu,
632	  FbBits    pm,
633	  int	    bpp)
634{
635    FbBits  *src;
636    int	    leftShiftEven, rightShiftEven;
637    FbBits  startmaskEven, endmaskEven;
638    int	    nmiddleEven;
639
640    FbBits  *dst;
641    int	    leftShiftOdd, rightShiftOdd;
642    FbBits  startmaskOdd, endmaskOdd;
643    int	    nmiddleOdd;
644
645    int	    leftShift, rightShift;
646    FbBits  startmask, endmask;
647    int	    nmiddle;
648
649    int	    srcX, dstX;
650
651    FbBits  bits, bits1;
652    int	    n;
653
654    Bool    destInvarient;
655    Bool    even;
656    FbDeclareMergeRop ();
657
658    FbInitializeMergeRop (alu, pm);
659    destInvarient = FbDestInvarientMergeRop();
660
661    srcLine += srcXEven >> FB_SHIFT;
662    dstLine += dstXEven >> FB_SHIFT;
663    srcXEven &= FB_MASK;
664    dstXEven &= FB_MASK;
665    srcXOdd &= FB_MASK;
666    dstXOdd &= FB_MASK;
667
668    FbMaskBits(dstXEven, width, startmaskEven, nmiddleEven, endmaskEven);
669    FbMaskBits(dstXOdd, width, startmaskOdd, nmiddleOdd, endmaskOdd);
670
671    even = TRUE;
672    InitializeShifts(srcXEven, dstXEven, leftShiftEven, rightShiftEven);
673    InitializeShifts(srcXOdd, dstXOdd, leftShiftOdd, rightShiftOdd);
674    while (height--)
675    {
676	src = srcLine;
677	dst = dstLine;
678	if (even)
679	{
680	    srcX = srcXEven;
681	    dstX = dstXEven;
682	    startmask = startmaskEven;
683	    endmask = endmaskEven;
684	    nmiddle = nmiddleEven;
685	    leftShift = leftShiftEven;
686	    rightShift = rightShiftEven;
687	    srcLine += srcStrideEven;
688	    dstLine += dstStrideEven;
689	    even = FALSE;
690	}
691	else
692	{
693	    srcX = srcXOdd;
694	    dstX = dstXOdd;
695	    startmask = startmaskOdd;
696	    endmask = endmaskOdd;
697	    nmiddle = nmiddleOdd;
698	    leftShift = leftShiftOdd;
699	    rightShift = rightShiftOdd;
700	    srcLine += srcStrideOdd;
701	    dstLine += dstStrideOdd;
702	    even = TRUE;
703	}
704	if (srcX == dstX)
705	{
706	    if (startmask)
707	    {
708		bits = READ(src++);
709		WRITE(dst, FbDoMaskMergeRop (bits, READ(dst), startmask));
710		dst++;
711	    }
712	    n = nmiddle;
713	    if (destInvarient)
714	    {
715		while (n--)
716		{
717		    bits = READ(src++);
718		    WRITE(dst, FbDoDestInvarientMergeRop(bits));
719		    dst++;
720		}
721	    }
722	    else
723	    {
724		while (n--)
725		{
726		    bits = READ(src++);
727		    WRITE(dst, FbDoMergeRop (bits, READ(dst)));
728		    dst++;
729		}
730	    }
731	    if (endmask)
732	    {
733		bits = READ(src);
734		WRITE(dst, FbDoMaskMergeRop(bits, READ(dst), endmask));
735	    }
736	}
737	else
738	{
739	    bits = 0;
740	    if (srcX > dstX)
741		bits = READ(src++);
742	    if (startmask)
743	    {
744		bits1 = FbScrLeft(bits, leftShift);
745		bits = READ(src++);
746		bits1 |= FbScrRight(bits, rightShift);
747		WRITE(dst, FbDoMaskMergeRop (bits1, READ(dst), startmask));
748		dst++;
749	    }
750	    n = nmiddle;
751	    if (destInvarient)
752	    {
753		while (n--)
754		{
755		    bits1 = FbScrLeft(bits, leftShift);
756		    bits = READ(src++);
757		    bits1 |= FbScrRight(bits, rightShift);
758		    WRITE(dst, FbDoDestInvarientMergeRop(bits1));
759		    dst++;
760		}
761	    }
762	    else
763	    {
764		while (n--)
765		{
766		    bits1 = FbScrLeft(bits, leftShift);
767		    bits = READ(src++);
768		    bits1 |= FbScrRight(bits, rightShift);
769		    WRITE(dst, FbDoMergeRop(bits1, READ(dst)));
770		    dst++;
771		}
772	    }
773	    if (endmask)
774	    {
775		bits1 = FbScrLeft(bits, leftShift);
776		if (FbScrLeft(endmask, rightShift))
777		{
778		    bits = READ(src);
779		    bits1 |= FbScrRight(bits, rightShift);
780		}
781		WRITE(dst, FbDoMaskMergeRop (bits1, READ(dst), endmask));
782	    }
783	}
784    }
785}
786
787#ifdef FB_24BIT
788void
789fbBltOdd24 (FbBits	*srcLine,
790	    FbStride	srcStrideEven,
791	    FbStride	srcStrideOdd,
792	    int		srcXEven,
793	    int		srcXOdd,
794
795	    FbBits	*dstLine,
796	    FbStride	dstStrideEven,
797	    FbStride	dstStrideOdd,
798	    int		dstXEven,
799	    int		dstXOdd,
800
801	    int		width,
802	    int		height,
803
804	    int		alu,
805	    FbBits	pm)
806{
807    Bool    even = TRUE;
808
809    while (height--)
810    {
811	if (even)
812	{
813	    fbBlt24Line (srcLine, srcXEven, dstLine, dstXEven,
814			 width, alu, pm, FALSE);
815	    srcLine += srcStrideEven;
816	    dstLine += dstStrideEven;
817	    even = FALSE;
818	}
819	else
820	{
821	    fbBlt24Line (srcLine, srcXOdd, dstLine, dstXOdd,
822			 width, alu, pm, FALSE);
823	    srcLine += srcStrideOdd;
824	    dstLine += dstStrideOdd;
825	    even = TRUE;
826	}
827    }
828#if 0
829    fprintf (stderr, "\n");
830#endif
831}
832#endif
833
834#endif
835
836#if FB_STIP_SHIFT != FB_SHIFT
837void
838fbSetBltOdd (FbStip	*stip,
839	     FbStride	stipStride,
840	     int	srcX,
841	     FbBits	**bits,
842	     FbStride	*strideEven,
843	     FbStride	*strideOdd,
844	     int	*srcXEven,
845	     int	*srcXOdd)
846{
847    int	    srcAdjust;
848    int	    strideAdjust;
849
850    /*
851     * bytes needed to align source
852     */
853    srcAdjust = (((int) stip) & (FB_MASK >> 3));
854    /*
855     * FbStip units needed to align stride
856     */
857    strideAdjust = stipStride & (FB_MASK >> FB_STIP_SHIFT);
858
859    *bits = (FbBits *) ((char *) stip - srcAdjust);
860    if (srcAdjust)
861    {
862	*strideEven = FbStipStrideToBitsStride (stipStride + 1);
863	*strideOdd = FbStipStrideToBitsStride (stipStride);
864
865	*srcXEven = srcX + (srcAdjust << 3);
866	*srcXOdd = srcX + (srcAdjust << 3) - (strideAdjust << FB_STIP_SHIFT);
867    }
868    else
869    {
870	*strideEven = FbStipStrideToBitsStride (stipStride);
871	*strideOdd = FbStipStrideToBitsStride (stipStride + 1);
872
873	*srcXEven = srcX;
874	*srcXOdd = srcX + (strideAdjust << FB_STIP_SHIFT);
875    }
876}
877#endif
878
879void
880fbBltStip (FbStip   *src,
881	   FbStride srcStride,	    /* in FbStip units, not FbBits units */
882	   int	    srcX,
883
884	   FbStip   *dst,
885	   FbStride dstStride,	    /* in FbStip units, not FbBits units */
886	   int	    dstX,
887
888	   int	    width,
889	   int	    height,
890
891	   int	    alu,
892	   FbBits   pm,
893	   int	    bpp)
894{
895#if FB_STIP_SHIFT != FB_SHIFT
896    if (FB_STIP_ODDSTRIDE(srcStride) || FB_STIP_ODDPTR(src) ||
897	FB_STIP_ODDSTRIDE(dstStride) || FB_STIP_ODDPTR(dst))
898    {
899	FbStride    srcStrideEven, srcStrideOdd;
900	FbStride    dstStrideEven, dstStrideOdd;
901	int	    srcXEven, srcXOdd;
902	int	    dstXEven, dstXOdd;
903	FbBits	    *s, *d;
904	int	    sx, dx;
905
906	src += srcX >> FB_STIP_SHIFT;
907	srcX &= FB_STIP_MASK;
908	dst += dstX >> FB_STIP_SHIFT;
909	dstX &= FB_STIP_MASK;
910
911	fbSetBltOdd (src, srcStride, srcX,
912		     &s,
913		     &srcStrideEven, &srcStrideOdd,
914		     &srcXEven, &srcXOdd);
915
916	fbSetBltOdd (dst, dstStride, dstX,
917		     &d,
918		     &dstStrideEven, &dstStrideOdd,
919		     &dstXEven, &dstXOdd);
920
921#ifdef FB_24BIT
922	if (bpp == 24 && !FbCheck24Pix (pm))
923	{
924	    fbBltOdd24  (s, srcStrideEven, srcStrideOdd,
925			 srcXEven, srcXOdd,
926
927			 d, dstStrideEven, dstStrideOdd,
928			 dstXEven, dstXOdd,
929
930			 width, height, alu, pm);
931	}
932	else
933#endif
934	{
935	    fbBltOdd (s, srcStrideEven, srcStrideOdd,
936		      srcXEven, srcXOdd,
937
938		      d, dstStrideEven, dstStrideOdd,
939		      dstXEven, dstXOdd,
940
941		      width, height, alu, pm, bpp);
942	}
943    }
944    else
945#endif
946    {
947	fbBlt ((FbBits *) src, FbStipStrideToBitsStride (srcStride),
948	       srcX,
949	       (FbBits *) dst, FbStipStrideToBitsStride (dstStride),
950	       dstX,
951	       width, height,
952	       alu, pm, bpp, FALSE, FALSE);
953    }
954}
955