First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / xf4bpp / vgaBitBlt.c
blob2e89f43b78f20c2112d6d4ec9b84853cc6eeca12
1 /* GJA -- span move routines */
3 #ifdef HAVE_XORG_CONFIG_H
4 #include <xorg-config.h>
5 #endif
7 #include "xf4bpp.h"
8 #include "OScompiler.h"
9 #include "vgaReg.h"
10 #include "vgaVideo.h"
12 #include "xf86str.h" /* for pScrn->vtSema */
13 extern ScrnInfoPtr *xf86Screens;
15 #ifndef PC98_EGC /* not PC98_EGC */
16 /* NOTE: It seems that there is no way to program the VGA to copy just
17 * a part of a byte in the smarter modes. Therefore we copy the boundaries
18 * plane by plane.
20 #define WORDSZ 8
21 /* The fast blit code requires WORDSZ = 8 for its read-modify write cycle.
22 * Therefore, we do not fully implement the other options.
24 #define HIGHPLANEMASK 0x08
25 #define HIGHPLANEINDEX 3
27 /* Of course, we want the following anyway:
28 * (Yes, they're identical now.)
30 #define SMEM(x,y) ( VIDBASE(pWin) + (y) * BYTES_PER_LINE(pWin) + (x) )
31 #define DMEM(x,y) ( VIDBASE(pWin) + (y) * BYTES_PER_LINE(pWin) + (x) )
33 #define WORD8 unsigned char
34 #define LW8 BYTES_PER_LINE(pWin) /* Line width */
35 #define WSHIFT8 0x3
36 #define WMASK8 0x07
37 /* NOTE: lmask[8] matters. It must be different from lmask[0] */
38 static unsigned char lmasktab[] = {
39 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF
40 } ;
41 static unsigned char rmasktab[] = {
42 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
43 } ;
45 #define LMASK8(n) lmasktab[n]
46 #define RMASK8(n) rmasktab[n]
47 #define SWAPB8(x) (x)
49 #if (WORDSZ == 8)
51 #define WORD WORD8
52 #define LW LW8
53 #define WSHIFT WSHIFT8
54 #define WMASK WMASK8
56 #define LMASK(n) LMASK8(n)
57 #define RMASK(n) RMASK8(n)
58 #define SWAPB(x) SWAPB8(x)
60 #endif /* WORDSZ == 8 */
62 #define DO_ALU(dst,src,mask,alu) {\
63 int _ndst, _odst; _odst = dst; \
64 switch ( alu ) { \
65 case GXclear: \
66 _ndst = 0; break; \
67 case GXand: \
68 _ndst = src & _odst; break; \
69 case GXandReverse: \
70 _ndst = src & ~ _odst; break; \
71 case GXcopy: \
72 _ndst = src; break; \
73 case GXandInverted: \
74 _ndst = ~ src & _odst; break; \
75 default: \
76 case GXnoop: \
77 _ndst = _odst; break; \
78 case GXxor: \
79 _ndst = src ^ _odst; break; \
80 case GXor: \
81 _ndst = src | _odst; break; \
82 case GXnor: \
83 _ndst = ~ src & ~ _odst; break; \
84 case GXequiv: \
85 _ndst = ~ src ^ _odst; break; \
86 case GXinvert: \
87 _ndst = ~ _odst; break; \
88 case GXorReverse: \
89 _ndst = src | ~ _odst; break; \
90 case GXcopyInverted: \
91 _ndst = ~ src; break; \
92 case GXorInverted: \
93 _ndst = ~ src | _odst; break; \
94 case GXnand: \
95 _ndst = ~ src | ~ _odst; break; \
96 case GXset: \
97 _ndst = ~0; break; \
98 } \
99 dst = (_odst & ~(mask)) | (_ndst & (mask)); \
102 static void aligned_blit(
103 WindowPtr, int, int, int, int, int, int, int, int
106 static void aligned_blit_center(
107 WindowPtr, int, int, int, int, int, int
110 static void shift(
111 WindowPtr, int, int, int, int, int, int, int
114 static void shift_thin_rect(
115 WindowPtr, int, int, int, int, int, int, int
118 static void shift_center(
119 WindowPtr, int, int, int, int, int, int, int
122 void xf4bppBitBlt(pWin,alu,writeplanes,x0,y0,x1,y1,w,h)
123 WindowPtr pWin; /* GJA */
124 int alu;
125 int writeplanes; /* planes */
126 int x0, y0, x1, y1, w, h;
128 IOADDRESS REGBASE;
129 int plane, bit;
131 if ( !w || !h ) return;
133 if ( ! xf86Screens[((DrawablePtr)pWin)->pScreen->myNum]->vtSema ) {
134 xf4bppOffBitBlt(pWin,alu,writeplanes,x0,y0,x1,y1,w,h);
135 return;
138 REGBASE =
139 xf86Screens[((DrawablePtr)pWin)->pScreen->myNum]->domainIOBase + 0x300;
141 /* 0x7, not WMASK: it is hardware dependant */
142 if ( ((x0 - x1) & 0x7) || (alu != GXcopy) ) {
143 /* Use slow copy */
144 SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
145 SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
146 SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
147 SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
149 for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX ;
150 plane ; plane >>= 1, bit-- )
153 if ( writeplanes & plane) {
154 SetVideoGraphics(Read_Map_SelectIndex, bit);
155 SetVideoSequencer(Mask_MapIndex, plane);
157 shift(pWin,x0,x1,y0,y1,w,h,alu);
160 } else {
161 aligned_blit(pWin,x0,x1,y0,y1,w,h,alu,writeplanes);
165 /* Copy a span a number of places to the right.
167 static void
168 shift(pWin,x0,x1,y0,y1,w,h,alu)
169 WindowPtr pWin; /* GJA */
170 int x0; /* left edge of source */
171 int x1; /* left edge of target */
172 int y0;
173 int y1;
174 int w; /* length of source, and of target */
175 int h;
176 int alu;
178 if ( ((x1 & WMASK) + w) <= WORDSZ ) {
179 shift_thin_rect(pWin,x0,x1,y0,y1,w,h,alu);
180 } else if ( x1 > x0 ) { /* Shift right: start right */
181 int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
183 if ( r1 ) /* right edge */
184 shift_thin_rect(pWin,x0+w-r1,x1+w-r1,y0,y1,r1,h,alu);
185 shift_center(pWin,x0,x1,y0,y1,w,h,alu);
186 if ( l1 ) /* left edge */
187 shift_thin_rect(pWin,x0,x1,y0,y1,(WORDSZ-l1),h,alu);
188 } else {
189 int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
191 if ( l1 ) /* left edge */
192 shift_thin_rect(pWin,x0,x1,y0,y1,(WORDSZ-l1),h,alu);
193 shift_center(pWin,x0,x1,y0,y1,w,h,alu);
194 if ( r1 ) /* right edge */
195 shift_thin_rect(pWin,x0+w-r1,x1+w-r1,y0,y1,r1,h,alu);
199 /* The whole rectangle is so thin that it fits in one byte written */
200 static void
201 shift_thin_rect(pWin,x0,x1,y0,y1,w,h,alu)
202 WindowPtr pWin; /* GJA */
203 int x0; /* left edge of source */
204 int x1; /* left edge of target */
205 int y0;
206 int y1;
207 int w; /* length of source, and of target */
208 int h;
209 int alu;
211 int l0 = x0 & WMASK; /* Left edge of source, as bit */
212 int l1 = x1 & WMASK; /* Left edge of target, as bit */
213 int L0 = x0 >> WSHIFT; /* Left edge of source, as byte */
214 int L1 = x1 >> WSHIFT; /* Left edge of target, as byte */
215 int pad;
216 int htmp;
217 int mask;
218 int tmp;
219 int bs;
221 volatile unsigned char *sp, *dp;
223 mask = RMASK(l1) & LMASK(l1+w);
224 bs = (x1 - x0) & WMASK;
226 if ( y1 > y0 ) { /* Move down, start at the bottom */
227 pad = - BYTES_PER_LINE(pWin);
228 sp = SMEM(L0,y0+h-1);
229 dp = DMEM(L1,y1+h-1);
230 } else { /* Move up, start at the top */
231 pad = BYTES_PER_LINE(pWin);
232 sp = SMEM(L0,y0);
233 dp = DMEM(L1,y1);
236 if ( l0+w > WORDSZ ) {
237 /* Need two bytes */
238 for ( htmp = h ; htmp ; htmp-- ) {
239 tmp = (sp[0] << (WORDSZ - bs));
240 sp++;
241 tmp |= (sp[0] >> bs);
242 sp--;
243 DO_ALU(dp[0],tmp,mask,alu);
244 dp += pad;
245 sp += pad;
247 } else if ( l0 <= l1 ) {
248 /* Need one byte, shifted right */
249 for ( htmp = h ; htmp ; htmp-- ) {
250 tmp = (sp[0] >> bs);
251 DO_ALU(dp[0],tmp,mask,alu);
252 dp += pad;
253 sp += pad;
255 } else {
256 /* Need one byte, shifted left */
257 for ( htmp = h ; htmp ; htmp-- ) {
258 tmp = (sp[0] << (WORDSZ - bs));
259 DO_ALU(dp[0],tmp,mask,alu);
260 dp += pad;
261 sp += pad;
266 static void
267 shift_center(pWin,x0,x1,y0,y1,w,h,alu)
268 WindowPtr pWin; /* GJA */
269 int x0; /* left edge of source */
270 int x1; /* left edge of target */
271 int y0;
272 int y1;
273 int w; /* length of source, and of target */
274 int h;
275 int alu;
277 int l1 = x1 & WMASK; /* Left edge of target, as bit */
278 int r1 = (x1 + w) & WMASK; /* Right edge of target, as bit */
279 int pad;
280 int htmp, wtmp; /* Temporaries for indices over height and width */
281 volatile unsigned char tmp; /* Temporary result of the shifts */
282 int bs;
283 int rem; /* Remaining bits; temporary in loop */
284 int bytecnt;
286 volatile unsigned char *sp, *dp;
288 bs = (x1 - x0) & WMASK;
290 if ( l1 ) {
291 bytecnt = (w - (WORDSZ - l1) - r1) >> WSHIFT;
292 sp = SMEM( ((x0 + (WORDSZ - l1)) >> WSHIFT), y0);
293 dp = DMEM( ((x1 + (WORDSZ - l1)) >> WSHIFT), y1);
294 } else {
295 bytecnt = (w - r1) >> WSHIFT;
296 sp = SMEM( (x0 >> WSHIFT), y0);
297 dp = DMEM( (x1 >> WSHIFT), y1);
300 if ( y1 > y0 ) { /* Move down, start at the bottom */
301 if ( x1 > x0 ) { /* Move right, start right */
302 pad = - BYTES_PER_LINE(pWin) + bytecnt;
303 sp += BYTES_PER_LINE(pWin) * (h - 1) + bytecnt - 1;
304 dp += BYTES_PER_LINE(pWin) * (h - 1) + bytecnt - 1;
305 } else { /* Move left, start left */
306 pad = - BYTES_PER_LINE(pWin) - bytecnt;
307 sp += BYTES_PER_LINE(pWin) * (h - 1);
308 dp += BYTES_PER_LINE(pWin) * (h - 1);
310 } else { /* Move up, start at the top */
311 if ( x1 > x0 ) { /* Move right, start right */
312 pad = BYTES_PER_LINE(pWin) + bytecnt;
313 sp += bytecnt - 1;
314 dp += bytecnt - 1;
315 } else { /* Move left, start left */
316 pad = BYTES_PER_LINE(pWin) - bytecnt;
317 sp += 0;
318 dp += 0;
322 if ( x1 > x0 ) { /* Move right, start right */
323 if ( bs == 0 ) { /* No shift. Need one byte only */
324 for ( htmp = h ; htmp ; htmp-- ) {
325 for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
326 tmp = sp[0];
327 DO_ALU(dp[0],tmp,~0,alu);
328 dp--;
329 sp--;
331 dp += pad;
332 sp += pad;
334 } else {
335 for ( htmp = h ; htmp ; htmp-- ) {
336 if ( bytecnt ) {
337 sp++;
338 rem = sp[0];
339 sp--;
340 for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
341 tmp = (rem >> bs);
342 rem = sp[0];
343 tmp |= (rem << (WORDSZ - bs)) ;
344 DO_ALU(dp[0],tmp,~0,alu);
345 dp--;
346 sp--;
349 dp += pad;
350 sp += pad;
353 } else { /* x1 <= x0 */ /* Move left, start left */
354 if ( bs == 0 ) { /* No shift. Need one byte only */
355 for ( htmp = h ; htmp ; htmp-- ) {
356 for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
357 tmp = sp[0];
358 DO_ALU(dp[0],tmp,~0,alu);
359 dp++;
360 sp++;
362 dp += pad;
363 sp += pad;
365 } else {
366 for ( htmp = h ; htmp ; htmp-- ) {
367 if ( bytecnt ) {
368 rem = sp[0];
369 for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
370 tmp = (rem << (WORDSZ - bs));
371 sp++;
372 rem = sp[0];
373 sp--;
374 tmp |= (rem >> bs);
375 DO_ALU(dp[0],tmp,~0,alu);
376 dp++;
377 sp++;
380 dp += pad;
381 sp += pad;
387 /* Copy a rectangle.
389 static void
390 aligned_blit(pWin,x0,x1,y0,y1,w,h,alu,planes)
391 WindowPtr pWin; /* GJA */
392 int x0; /* left edge of source */
393 int x1; /* left edge of target */
394 int y0;
395 int y1;
396 int w; /* length of source, and of target */
397 int h;
398 int alu;
399 int planes;
401 IOADDRESS REGBASE =
402 xf86Screens[((DrawablePtr)pWin)->pScreen->myNum]->domainIOBase + 0x300;
403 int plane, bit;
405 if ( ((x1 & WMASK) + w) <= WORDSZ ) {
406 SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
407 SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
408 SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
409 SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
411 for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX;
412 plane ; plane >>= 1, bit-- )
414 if ( planes & plane) {
415 SetVideoGraphics(Read_Map_SelectIndex, bit);
416 SetVideoSequencer(Mask_MapIndex, plane);
418 shift_thin_rect(pWin,x0,x1,y0,y1,w,h,alu);
421 } else if ( x1 > x0 ) { /* Shift right: start right */
422 int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
424 if ( r1 ) { /* right edge */
425 SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
426 SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
427 SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
428 SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
430 for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX;
431 plane ; plane >>= 1, bit-- )
433 if ( planes & plane) {
434 SetVideoGraphics(Read_Map_SelectIndex, bit);
435 SetVideoSequencer(Mask_MapIndex, plane);
437 shift_thin_rect(pWin,x0+w-r1,x1+w-r1,y0,y1,r1,h,alu);
442 /* Center */
443 SetVideoGraphics(Graphics_ModeIndex, 1); /* Write mode 1 */
444 SetVideoSequencer(Mask_MapIndex, planes);
446 aligned_blit_center(pWin,x0,x1,y0,y1,w,h);
448 if ( l1 ) { /* left edge */
449 SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
450 SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
451 SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
452 SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
454 for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX;
455 plane ; plane >>= 1, bit-- )
457 if ( planes & plane) {
458 SetVideoGraphics(Read_Map_SelectIndex, bit);
459 SetVideoSequencer(Mask_MapIndex, plane);
461 shift_thin_rect(pWin,x0,x1,y0,y1,(WORDSZ-l1),h,alu);
465 } else {
466 int l1 = x1 & WMASK, r1 = (x1 + w) & WMASK;
468 if ( l1 ) { /* left edge */
469 SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
470 SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
471 SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
472 SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
474 for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX;
475 plane ; plane >>= 1, bit-- )
477 if ( planes & plane) {
478 SetVideoGraphics(Read_Map_SelectIndex, bit);
479 SetVideoSequencer(Mask_MapIndex, plane);
481 shift_thin_rect(pWin,x0,x1,y0,y1,(WORDSZ-l1),h,alu);
486 /* Center */
487 SetVideoGraphics(Graphics_ModeIndex, 1); /* Write mode 1 */
488 SetVideoSequencer(Mask_MapIndex, planes);
490 aligned_blit_center(pWin,x0,x1,y0,y1,w,h);
492 if ( r1 ) { /* right edge */
493 SetVideoGraphics(Enb_Set_ResetIndex, 0); /* All from CPU */
494 SetVideoGraphics(Bit_MaskIndex, 0xFF); /* All bits */
495 SetVideoGraphics(Graphics_ModeIndex, 0); /* Write mode 0 */
496 SetVideoGraphics(Data_RotateIndex, 0); /* Don't rotate, replace */
498 for ( plane = HIGHPLANEMASK, bit = HIGHPLANEINDEX ;
499 plane ; plane >>= 1, bit-- )
501 if ( planes & plane) {
502 SetVideoGraphics(Read_Map_SelectIndex, bit);
503 SetVideoSequencer(Mask_MapIndex, plane);
505 shift_thin_rect(pWin,x0+w-r1,x1+w-r1,y0,y1,r1,h,alu);
512 static void
513 aligned_blit_center(pWin,x0,x1,y0,y1,w,h)
514 WindowPtr pWin; /* GJA */
515 int x0; /* left edge of source */
516 int x1; /* left edge of target */
517 int y0;
518 int y1;
519 int w; /* length of source, and of target */
520 int h;
522 int l1 = x1 & WMASK; /* Left edge of target, as bit */
523 int r1 = (x1 + w) & WMASK; /* Right edge of target, as bit */
524 int pad;
525 int htmp, wtmp; /* Temporaries for indices over height and width */
526 volatile unsigned char tmp; /* Temporary result of the shifts */
527 int bytecnt;
529 volatile unsigned char *sp, *dp;
531 if ( l1 ) {
532 bytecnt = (w - (WORDSZ - l1) - r1) >> WSHIFT;
533 sp = SMEM( ((x0 + (WORDSZ - l1)) >> WSHIFT), y0);
534 dp = DMEM( ((x1 + (WORDSZ - l1)) >> WSHIFT), y1);
535 } else {
536 bytecnt = (w - r1) >> WSHIFT;
537 sp = SMEM( (x0 >> WSHIFT), y0);
538 dp = DMEM( (x1 >> WSHIFT), y1);
541 if ( y1 > y0 ) { /* Move down, start at the bottom */
542 if ( x1 > x0 ) { /* Move right, start right */
543 pad = - BYTES_PER_LINE(pWin) + bytecnt;
544 sp += BYTES_PER_LINE(pWin) * (h - 1) + bytecnt - 1;
545 dp += BYTES_PER_LINE(pWin) * (h - 1) + bytecnt - 1;
546 } else { /* Move left, start left */
547 pad = - BYTES_PER_LINE(pWin) - bytecnt;
548 sp += BYTES_PER_LINE(pWin) * (h - 1);
549 dp += BYTES_PER_LINE(pWin) * (h - 1);
551 } else { /* Move up, start at the top */
552 if ( x1 > x0 ) { /* Move right, start right */
553 pad = BYTES_PER_LINE(pWin) + bytecnt;
554 sp += bytecnt - 1;
555 dp += bytecnt - 1;
556 } else { /* Move left, start left */
557 pad = BYTES_PER_LINE(pWin) - bytecnt;
558 sp += 0;
559 dp += 0;
563 if ( x1 > x0 ) { /* Move right, start right */
564 for ( htmp = h ; htmp ; htmp-- ) {
565 for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
566 tmp = sp[0];
567 dp[0] = tmp;
568 dp--;
569 sp--;
571 dp += pad;
572 sp += pad;
574 } else { /* x1 <= x0 */ /* Move left, start left */
575 for ( htmp = h ; htmp ; htmp-- ) {
576 for ( wtmp = bytecnt ; wtmp ; wtmp-- ) {
577 tmp = sp[0];
578 dp[0] = tmp;
579 dp++;
580 sp++;
582 dp += pad;
583 sp += pad;
587 #else /* PC98_EGC */
589 static void
590 egc_fast_blt (pWin, alu, writeplanes, x0, y0, x1, y1, w, h)
591 WindowPtr pWin;
592 const int alu, writeplanes ;
593 register int x0, x1 ;
594 int y0, y1 ;
595 register int w, h ;
597 register volatile unsigned char *src ;
598 register volatile unsigned char *dst ;
599 unsigned short *src_x ;
600 unsigned short *dst_x ;
601 int x_direction, y_interval ;
602 int src_off, dst_off ;
603 register int k, i ;
604 unsigned short ROP_value;
606 src = (unsigned char *)SCREENADDRESS( pWin, 0, y0);
607 dst = (unsigned char *)SCREENADDRESS( pWin, 0, y1);
609 /* Set Map Mask */
610 outw(EGC_PLANE, ~(writeplanes & VGA_ALLPLANES));
611 switch(alu) {
612 case GXnor: /* ~(S|D) */
613 ROP_value = 0x2903;
614 break;
615 case GXandInverted: /* ~S&D */
616 ROP_value = 0x290c;
617 break;
618 case GXand: /* S&D */
619 ROP_value = 0x29c0;
620 break;
621 case GXequiv: /* ~S ^ D */
622 ROP_value = 0x29c3;
623 break;
624 case GXxor: /* S^D */
625 ROP_value = 0x293c;
626 break;
627 case GXandReverse: /* S&~D */
628 ROP_value = 0x2930;
629 break;
630 case GXorReverse: /* S|~D */
631 ROP_value = 0x29f3;
632 break;
633 case GXnand: /* ~(S&D) */
634 ROP_value = 0x293f;
635 break;
636 case GXorInverted: /* ~S|D */
637 ROP_value = 0x29cf;
638 break;
639 case GXor: /* S|D */
640 ROP_value = 0x29fa;
641 break;
642 case GXcopyInverted: /* ~S */
643 ROP_value = 0x290f;
644 break;
645 case GXcopy: /* S */
646 default:
647 ROP_value = 0x29f0;
649 outw(EGC_MODE, ROP_value);
650 if ( y1 > y0 ) {
651 y_interval = - BYTES_PER_LINE(pWin) * 8 ;
652 src += BYTES_PER_LINE(pWin) * ( h - 1 ) ;
653 dst += BYTES_PER_LINE(pWin) * ( h - 1 ) ;
655 else {
656 y_interval = BYTES_PER_LINE(pWin) * 8 ;
659 src = (unsigned char *)((int)src << 3) ;
660 dst = (unsigned char *)((int)dst << 3) ;
662 if ( y1 > y0) {
663 x_direction = 0x1000 ;
664 src += x0 + w - 1 ;
665 dst += x1 + w - 1 ;
666 } else if ( y1 < y0 ) {
667 x_direction = 0 ;
668 src += x0 ;
669 dst += x1 ;
670 } else {
671 if ( x1 < x0 ) {
672 x_direction = 0 ;
673 src += x0 ;
674 dst += x1 ;
675 } else {
676 x_direction = 0x1000 ;
677 src += x0 + w - 1 ;
678 dst += x1 + w - 1 ;
681 outw ( EGC_LENGTH , w - 1 ) ;
683 for ( ; h-- ; ) {
684 if ( x_direction ) {
685 src_off = 15 - (int)src & 0xf ;
686 dst_off = 15 - (int)dst & 0xf ;
687 } else {
688 src_off = (int)src & 0xf ;
689 dst_off = (int)dst & 0xf ;
691 #if defined(__NetBSD__) || defined(__OpenBSD__)
692 src_x = (unsigned short *)(((unsigned int)src >> 4 ) << 1) ;
693 dst_x = (unsigned short *)(((unsigned int)dst >> 4 ) << 1) ;
694 #else
695 src_x = (unsigned short *)(((int)src >> 4 ) << 1) ;
696 dst_x = (unsigned short *)(((int)dst >> 4 ) << 1) ;
697 #endif
698 k = ( src_off + w + 15 ) >> 4 ;
699 if ( src_off < dst_off ) {
700 if ( ((src_off + w - 1 ) >> 4) < ((dst_off + w - 1) >> 4)) k++ ;
702 if ( src_off > dst_off ) {
703 if ( ((src_off + w - 1) >> 4 ) == ((dst_off + w - 1) >> 4) ) k++ ;
704 if ( x_direction ) dst_x ++ ;
705 else dst_x -- ;
707 outw ( EGC_ADD , x_direction | src_off | dst_off << 4 );
708 if ( x_direction ) {
709 wcopyl ( src_x, dst_x, k, VIDBASE(pWin) ) ;
710 } else {
711 wcopyr ( src_x, dst_x, k, VIDBASE(pWin) ) ;
713 src += y_interval ;
714 dst += y_interval ;
716 outw ( EGC_ADD, 0 ) ;
717 outw ( EGC_LENGTH , 0xf );
718 return;
721 void
722 xf4bppBitBlt( pWin,alu, writeplanes, x0, y0, x1, y1, w, h )
723 WindowPtr pWin; /* GJA */
724 int alu;
725 int writeplanes; /* planes */
726 int x0, y0, x1, y1, w, h;
728 if ( ! xf86Screens[((DrawablePtr)pWin)->pScreen->myNum]->vtSema ) {
729 xf4bppOffBitBlt( pWin, alu, writeplanes,
730 x0, y0, x1, y1, w, h );
731 return;
734 switch ( alu ) {
735 case GXclear: /* 0x0 Zero 0 */
736 case GXinvert: /* 0xa NOT dst */
737 case GXset: /* 0xf 1 */
738 xf4bppFillSolid( pWin, VGA_ALLPLANES, alu, writeplanes, x1, y1, w, h ) ;
739 /* x1, y1, GJA */
740 case GXnoop: /* 0x5 dst */
741 return ;
742 default:
743 break ;
746 egc_fast_blt ( pWin, alu, writeplanes, x0, y0, x1, y1, w, h);
747 return;
749 #endif