1 /* GJA -- span move routines */
3 #ifdef HAVE_XORG_CONFIG_H
4 #include <xorg-config.h>
8 #include "OScompiler.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
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 */
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
41 static unsigned char rmasktab
[] = {
42 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
45 #define LMASK8(n) lmasktab[n]
46 #define RMASK8(n) rmasktab[n]
53 #define WSHIFT WSHIFT8
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; \
68 _ndst = src & _odst; break; \
70 _ndst = src & ~ _odst; break; \
74 _ndst = ~ src & _odst; break; \
77 _ndst = _odst; break; \
79 _ndst = src ^ _odst; break; \
81 _ndst = src | _odst; break; \
83 _ndst = ~ src & ~ _odst; break; \
85 _ndst = ~ src ^ _odst; break; \
87 _ndst = ~ _odst; break; \
89 _ndst = src | ~ _odst; break; \
90 case GXcopyInverted: \
91 _ndst = ~ src; break; \
93 _ndst = ~ src | _odst; break; \
95 _ndst = ~ src | ~ _odst; break; \
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
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 */
125 int writeplanes
; /* planes */
126 int x0
, y0
, x1
, y1
, w
, h
;
131 if ( !w
|| !h
) return;
133 if ( ! xf86Screens
[((DrawablePtr
)pWin
)->pScreen
->myNum
]->vtSema
) {
134 xf4bppOffBitBlt(pWin
,alu
,writeplanes
,x0
,y0
,x1
,y1
,w
,h
);
139 xf86Screens
[((DrawablePtr
)pWin
)->pScreen
->myNum
]->domainIOBase
+ 0x300;
141 /* 0x7, not WMASK: it is hardware dependant */
142 if ( ((x0
- x1
) & 0x7) || (alu
!= GXcopy
) ) {
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
);
161 aligned_blit(pWin
,x0
,x1
,y0
,y1
,w
,h
,alu
,writeplanes
);
165 /* Copy a span a number of places to the right.
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 */
174 int w
; /* length of source, and of target */
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
);
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 */
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 */
207 int w
; /* length of source, and of target */
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 */
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
);
236 if ( l0
+w
> WORDSZ
) {
238 for ( htmp
= h
; htmp
; htmp
-- ) {
239 tmp
= (sp
[0] << (WORDSZ
- bs
));
241 tmp
|= (sp
[0] >> bs
);
243 DO_ALU(dp
[0],tmp
,mask
,alu
);
247 } else if ( l0
<= l1
) {
248 /* Need one byte, shifted right */
249 for ( htmp
= h
; htmp
; htmp
-- ) {
251 DO_ALU(dp
[0],tmp
,mask
,alu
);
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
);
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 */
273 int w
; /* length of source, and of target */
277 int l1
= x1
& WMASK
; /* Left edge of target, as bit */
278 int r1
= (x1
+ w
) & WMASK
; /* Right edge of target, as bit */
280 int htmp
, wtmp
; /* Temporaries for indices over height and width */
281 volatile unsigned char tmp
; /* Temporary result of the shifts */
283 int rem
; /* Remaining bits; temporary in loop */
286 volatile unsigned char *sp
, *dp
;
288 bs
= (x1
- x0
) & WMASK
;
291 bytecnt
= (w
- (WORDSZ
- l1
) - r1
) >> WSHIFT
;
292 sp
= SMEM( ((x0
+ (WORDSZ
- l1
)) >> WSHIFT
), y0
);
293 dp
= DMEM( ((x1
+ (WORDSZ
- l1
)) >> WSHIFT
), y1
);
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
;
315 } else { /* Move left, start left */
316 pad
= BYTES_PER_LINE(pWin
) - bytecnt
;
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
-- ) {
327 DO_ALU(dp
[0],tmp
,~0,alu
);
335 for ( htmp
= h
; htmp
; htmp
-- ) {
340 for ( wtmp
= bytecnt
; wtmp
; wtmp
-- ) {
343 tmp
|= (rem
<< (WORDSZ
- bs
)) ;
344 DO_ALU(dp
[0],tmp
,~0,alu
);
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
-- ) {
358 DO_ALU(dp
[0],tmp
,~0,alu
);
366 for ( htmp
= h
; htmp
; htmp
-- ) {
369 for ( wtmp
= bytecnt
; wtmp
; wtmp
-- ) {
370 tmp
= (rem
<< (WORDSZ
- bs
));
375 DO_ALU(dp
[0],tmp
,~0,alu
);
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 */
396 int w
; /* length of source, and of target */
402 xf86Screens
[((DrawablePtr
)pWin
)->pScreen
->myNum
]->domainIOBase
+ 0x300;
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
);
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
);
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
);
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
);
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 */
519 int w
; /* length of source, and of target */
522 int l1
= x1
& WMASK
; /* Left edge of target, as bit */
523 int r1
= (x1
+ w
) & WMASK
; /* Right edge of target, as bit */
525 int htmp
, wtmp
; /* Temporaries for indices over height and width */
526 volatile unsigned char tmp
; /* Temporary result of the shifts */
529 volatile unsigned char *sp
, *dp
;
532 bytecnt
= (w
- (WORDSZ
- l1
) - r1
) >> WSHIFT
;
533 sp
= SMEM( ((x0
+ (WORDSZ
- l1
)) >> WSHIFT
), y0
);
534 dp
= DMEM( ((x1
+ (WORDSZ
- l1
)) >> WSHIFT
), y1
);
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
;
556 } else { /* Move left, start left */
557 pad
= BYTES_PER_LINE(pWin
) - bytecnt
;
563 if ( x1
> x0
) { /* Move right, start right */
564 for ( htmp
= h
; htmp
; htmp
-- ) {
565 for ( wtmp
= bytecnt
; wtmp
; wtmp
-- ) {
574 } else { /* x1 <= x0 */ /* Move left, start left */
575 for ( htmp
= h
; htmp
; htmp
-- ) {
576 for ( wtmp
= bytecnt
; wtmp
; wtmp
-- ) {
590 egc_fast_blt (pWin
, alu
, writeplanes
, x0
, y0
, x1
, y1
, w
, h
)
592 const int alu
, writeplanes
;
593 register int x0
, x1
;
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
;
604 unsigned short ROP_value
;
606 src
= (unsigned char *)SCREENADDRESS( pWin
, 0, y0
);
607 dst
= (unsigned char *)SCREENADDRESS( pWin
, 0, y1
);
610 outw(EGC_PLANE
, ~(writeplanes
& VGA_ALLPLANES
));
612 case GXnor
: /* ~(S|D) */
615 case GXandInverted
: /* ~S&D */
618 case GXand
: /* S&D */
621 case GXequiv
: /* ~S ^ D */
624 case GXxor
: /* S^D */
627 case GXandReverse
: /* S&~D */
630 case GXorReverse
: /* S|~D */
633 case GXnand
: /* ~(S&D) */
636 case GXorInverted
: /* ~S|D */
642 case GXcopyInverted
: /* ~S */
649 outw(EGC_MODE
, ROP_value
);
651 y_interval
= - BYTES_PER_LINE(pWin
) * 8 ;
652 src
+= BYTES_PER_LINE(pWin
) * ( h
- 1 ) ;
653 dst
+= BYTES_PER_LINE(pWin
) * ( h
- 1 ) ;
656 y_interval
= BYTES_PER_LINE(pWin
) * 8 ;
659 src
= (unsigned char *)((int)src
<< 3) ;
660 dst
= (unsigned char *)((int)dst
<< 3) ;
663 x_direction
= 0x1000 ;
666 } else if ( y1
< y0
) {
676 x_direction
= 0x1000 ;
681 outw ( EGC_LENGTH
, w
- 1 ) ;
685 src_off
= 15 - (int)src
& 0xf ;
686 dst_off
= 15 - (int)dst
& 0xf ;
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) ;
695 src_x
= (unsigned short *)(((int)src
>> 4 ) << 1) ;
696 dst_x
= (unsigned short *)(((int)dst
>> 4 ) << 1) ;
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
++ ;
707 outw ( EGC_ADD
, x_direction
| src_off
| dst_off
<< 4 );
709 wcopyl ( src_x
, dst_x
, k
, VIDBASE(pWin
) ) ;
711 wcopyr ( src_x
, dst_x
, k
, VIDBASE(pWin
) ) ;
716 outw ( EGC_ADD
, 0 ) ;
717 outw ( EGC_LENGTH
, 0xf );
722 xf4bppBitBlt( pWin
,alu
, writeplanes
, x0
, y0
, x1
, y1
, w
, h
)
723 WindowPtr pWin
; /* GJA */
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
);
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
) ;
740 case GXnoop
: /* 0x5 dst */
746 egc_fast_blt ( pWin
, alu
, writeplanes
, x0
, y0
, x1
, y1
, w
, h
);