d88b0836738e1c7d118c8db725372d147d427abc
4 #include <ddk/ntddvdeo.h>
5 #include <ddk/winddi.h>
9 UCHAR PreCalcReverseByte
[256];
17 static ULONG UnpackPixel
[256];
19 static unsigned char leftMask
;
20 static int byteCounter
;
21 static unsigned char rightMask
;
23 #define READ_REGISTER_UCHAR(p) (*((volatile UCHAR *)(p)))
24 #define WRITE_REGISTER_UCHAR(p,c) (*((volatile CHAR *)(p))) = (c)
37 div_t div(int num
, int denom
)
40 if (num
> 0 && denom
< 0) {
46 if (num
< 0 && denom
> 0)
57 /*int mod(int num, int denom)
59 div_t dvt = div(num, denom);
63 BYTE
bytesPerPixel(ULONG Format
)
65 // This function is taken from /subsys/win32k/eng/surface.c
66 // FIXME: GDI bitmaps are supposed to be pixel-packed. Right now if the
67 // pixel size if < 1 byte we expand it to 1 byte for simplicities sake
147 for (j
= 0; j
< 256; j
++)
149 PreCalcReverseByte
[j
] =
150 (((j
>> 0) & 0x1) << 7) |
151 (((j
>> 1) & 0x1) << 6) |
152 (((j
>> 2) & 0x1) << 5) |
153 (((j
>> 3) & 0x1) << 4) |
154 (((j
>> 4) & 0x1) << 3) |
155 (((j
>> 5) & 0x1) << 2) |
156 (((j
>> 6) & 0x1) << 1) |
157 (((j
>> 7) & 0x1) << 0);
160 for (j
= 0; j
< 256; j
++)
163 (((j
>> 0) & 0x1) << 4) |
164 (((j
>> 1) & 0x1) << 0) |
165 (((j
>> 2) & 0x1) << 12) |
166 (((j
>> 3) & 0x1) << 8) |
167 (((j
>> 4) & 0x1) << 20) |
168 (((j
>> 5) & 0x1) << 16) |
169 (((j
>> 6) & 0x1) << 28) |
170 (((j
>> 7) & 0x1) << 24);
175 get_masks(int x
, int w
)
179 leftMask
= rightMask
= 0;
185 rightMask
= (unsigned char)(0xff00 >> tmp
);
190 byteCounter
-= (8 - tmp
);
191 leftMask
= (0xff >> tmp
);
194 if (byteCounter
< 0) {
195 leftMask
&= rightMask
;
202 VOID
vgaPutPixel(INT x
, INT y
, UCHAR c
)
207 offset
= xconv
[x
]+y80
[y
];
209 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08);
210 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,maskbit
[x
]);
212 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
213 WRITE_REGISTER_UCHAR(vidmem
+ offset
, c
);
216 VOID
vgaPutByte(INT x
, INT y
, UCHAR c
)
220 offset
= xconv
[x
]+y80
[y
];
222 // Set the write mode
223 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08);
224 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,0xff);
226 WRITE_REGISTER_UCHAR(vidmem
+ offset
, c
);
229 VOID
vgaGetByte(ULONG offset
,
233 WRITE_PORT_USHORT((PUSHORT
)GRA_I
, 0x0304);
234 *i
= READ_REGISTER_UCHAR(vidmem
+ offset
);
235 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
236 *r
= READ_REGISTER_UCHAR(vidmem
+ offset
);
237 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x01);
238 *g
= READ_REGISTER_UCHAR(vidmem
+ offset
);
239 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
240 *b
= READ_REGISTER_UCHAR(vidmem
+ offset
);
243 INT
vgaGetPixel(INT x
, INT y
)
245 UCHAR mask
, b
, g
, r
, i
;
248 offset
= xconv
[x
]+y80
[y
];
249 vgaGetByte(offset
, &b
, &g
, &r
, &i
);
263 return(b
+2*g
+4*r
+8*i
);
266 BOOL
vgaHLine(INT x
, INT y
, INT len
, UCHAR c
)
270 ULONG orgpre1
, orgx
, midpre1
;
271 LONG ileftpix
, imidpix
, irightpix
;
277 for (i = x; i < x+len; i++ )
278 vgaPutPixel ( i, y, c );
283 // Calculate the left mask pixels, middle bytes and right mask pixel
284 ileftpix
= 7 - mod8(x
-1);
285 irightpix
= mod8(x
+len
);
286 imidpix
= (len
-ileftpix
-irightpix
) / 8;
288 pre1
= xconv
[(x
-1)&~7] + y80
[y
];
291 // check for overlap ( very short line )
292 if ( (ileftpix
+irightpix
) > len
)
294 int mask
= startmasks
[ileftpix
] & endmasks
[irightpix
];
296 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask
297 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,mask
);
299 a
= READ_REGISTER_UCHAR(vidmem
+ pre1
);
300 WRITE_REGISTER_UCHAR(vidmem
+ pre1
, c
);
309 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask
310 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,startmasks
[ileftpix
]);
312 a
= READ_REGISTER_UCHAR(vidmem
+ pre1
);
313 WRITE_REGISTER_UCHAR(vidmem
+ pre1
, c
);
315 // Prepare new x for the middle
321 midpre1
= xconv
[x
] + y80
[y
];
323 // Set mask to all pixels in byte
324 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08);
325 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0xff);
326 memset(vidmem
+midpre1
, c
, imidpix
); // write middle pixels, no need to read in latch because of the width
331 x
= orgx
+ len
- irightpix
;
332 pre1
= xconv
[x
] + y80
[y
];
334 // Write right pixels
335 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask bits
336 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, endmasks
[irightpix
]);
337 a
= READ_REGISTER_UCHAR(vidmem
+ pre1
);
338 WRITE_REGISTER_UCHAR(vidmem
+ pre1
, c
);
344 BOOL
vgaVLine(INT x
, INT y
, INT len
, UCHAR c
)
349 offset
= xconv
[x
]+y80
[y
];
352 vgaSetBitMaskRegister ( maskbit
[x
] );
354 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask
355 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,maskbit
[x
]);
358 for(i
=y
; i
<y
+len
; i
++)
360 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
361 WRITE_REGISTER_UCHAR(vidmem
+ offset
, c
);
368 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
370 BOOL
VGADDIIntersectRect(PRECTL prcDst
, PRECTL prcSrc1
, PRECTL prcSrc2
)
372 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
373 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
375 if (prcDst
->left
< prcDst
->right
) {
376 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
377 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
379 if (prcDst
->top
< prcDst
->bottom
)
390 void DIB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int Dest_lDelta
)
394 ULONG shift
= x
- (x
& ~0x7);
395 UCHAR pixel
, nextpixel
;
398 LONG stride
= w
>> 3;
400 /* Calculate the number of rightmost bytes not in a dword block. */
411 /* Reset the destination. */
412 for (j
= 0; j
< h
; j
++)
414 memset((PVOID
)((ULONG_PTR
)b
+ (j
* Dest_lDelta
)), 0, abs(Dest_lDelta
));
417 for (plane
= 0; plane
< 4; plane
++)
421 /* Select the plane we are reading in this iteration. */
422 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04);
423 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
);
425 for (j
= 0; j
< h
; j
++)
427 PULONG destline
= (PULONG
)dest
;
428 PUCHAR src
= vidmem
+ (y
+ j
) * SCREEN_STRIDE
+ left
;
429 /* Read the data for one plane for an eight aligned pixel block. */
430 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
)];
431 for (i
= 0; i
< stride
; i
++, src
++, destline
++)
433 /* Form the data for one plane for an aligned block in the destination. */
437 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
+ 1)];
438 pixel
|= (nextpixel
<< (8 - shift
));
440 /* Expand the plane data to 'chunky' format and store. */
441 *destline
|= (UnpackPixel
[pixel
] << plane
);
443 /* Handle any pixels not falling into a full block. */
448 /* Form the data for a complete block. */
452 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
+ 1)];
453 pixel
|= (nextpixel
<< (8 - shift
));
455 row
= UnpackPixel
[pixel
] << plane
;
457 /* Store the data for each pixel in the destination. */
458 for (i
= 0; i
< rightcount
; i
++)
460 ((PUCHAR
)destline
)[i
] |= (row
& 0xFF);
469 for (j
= 0; j
< h
; j
++)
471 for (i
= 0; i
< w
; i
+=2)
474 ULONG mask
= (i
< (w
- 1)) ? 0xFF : 0xF0;
476 c1
= (vgaGetPixel(x
+ i
, y
+ j
) << 4) | (vgaGetPixel(x
+ i
+ 1, y
+ j
));
477 c2
= ((PUCHAR
)b
)[(j
* Dest_lDelta
) + (i
>> 1)];
478 if ((c1
& mask
) != (c2
& mask
))
480 __asm__("int $3\n\t" : /* no outputs */ : /* no inputs */);
484 #endif /* VGA_VERIFY */
488 void DIB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int Dest_lDelta
)
489 // DIB blt from the VGA.
490 // For now we just do slow reads -- pixel by pixel, packing each one into the correct 4BPP format.
492 PBYTE pb
= b
, opb
= b
;
493 BOOLEAN edgePixel
= FALSE
;
499 // Check if the width is odd
508 for (i
=x
; i
<x2
; i
+=2)
510 b1
= vgaGetPixel(i
, j
);
511 b2
= vgaGetPixel(i
+1, j
);
512 *pb
= b2
| (b1
<< 4);
516 if(edgePixel
== TRUE
)
518 b1
= vgaGetPixel(x2
, j
);
523 opb
+= Dest_lDelta
; // new test code
524 pb
= opb
; // new test code
529 /* DIB blt to the VGA. */
530 void DIB_BltToVGA(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, int StartMod
)
539 for (i
= x
; i
< x2
; i
++)
542 offset
= xconv
[i
] + y80
[y
];
544 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // set the mask
545 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, maskbit
[i
]);
547 if (StartMod
== ((i
- x
) % 2))
549 for (j
= y
; j
< y2
; j
++)
551 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
552 WRITE_REGISTER_UCHAR(vidmem
+ offset
, (*pb
& 0xf0) >> 4);
559 for (j
= y
; j
< y2
; j
++)
561 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
562 WRITE_REGISTER_UCHAR(vidmem
+ offset
, *pb
& 0x0f);
568 if (StartMod
!= ((i
- x
) % 2))
576 /* DIB blt to the VGA. */
577 void DIB_BltToVGAWithXlate(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, XLATEOBJ
* Xlate
)
586 for (i
= x
; i
< x2
; i
++)
589 offset
= xconv
[i
] + y80
[y
];
591 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // set the mask
592 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, maskbit
[i
]);
594 if (0 == ((i
- x
) % 2))
596 for (j
= y
; j
< y2
; j
++)
598 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
599 WRITE_REGISTER_UCHAR(vidmem
+ offset
, XLATEOBJ_iXlate(Xlate
, (*pb
& 0xf0) >> 4));
606 for (j
= y
; j
< y2
; j
++)
608 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
609 WRITE_REGISTER_UCHAR(vidmem
+ offset
, XLATEOBJ_iXlate(Xlate
, *pb
& 0x0f));
615 if (0 != ((i
- x
) % 2))
622 void DIB_TransparentBltToVGA(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, ULONG trans
)
624 // DIB blt to the VGA.
625 // For now we just do slow writes -- pixel by pixel, packing each one into the correct 4BPP format.
627 PBYTE pb
= b
, opb
= b
;
628 BOOLEAN edgePixel
= FALSE
;
634 // Check if the width is odd
643 for (i
=x
; i
<x2
; i
+=2)
645 b1
= (*pb
& 0xf0) >> 4;
647 if(b1
!= trans
) vgaPutPixel(i
, j
, b1
);
648 if(b2
!= trans
) vgaPutPixel(i
+1, j
, b2
);
652 if(edgePixel
== TRUE
)
655 if(b1
!= trans
) vgaPutPixel(x2
, j
, b1
);
659 opb
+= Source_lDelta
;
660 pb
= opb
; // new test code
665 // This algorithm goes from left to right, storing each 4BPP pixel
666 // in an entire byte.
668 vgaReadScan ( int x
, int y
, int w
, void *b
)
670 unsigned char *vp
, *vpP
;
671 unsigned char data
, mask
, maskP
;
673 unsigned char plane_mask
;
677 ASSIGNMK4(x
, y
, maskP
)
679 WRITE_PORT_USHORT((PUSHORT
)GRA_I
, 0x0005); // read mode 0
680 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04); // read map select
684 for ( plane
=0, plane_mask
=1; plane
< 4; plane
++, plane_mask
<<=1 )
686 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
); // read map select
700 } while (mask
& leftMask
);
705 for (i
=byteCounter
; i
>0; i
--)
708 if (data
& 0x80) *bp
|= plane_mask
;
710 if (data
& 0x40) *bp
|= plane_mask
;
712 if (data
& 0x20) *bp
|= plane_mask
;
714 if (data
& 0x10) *bp
|= plane_mask
;
716 if (data
& 0x08) *bp
|= plane_mask
;
718 if (data
& 0x04) *bp
|= plane_mask
;
720 if (data
& 0x02) *bp
|= plane_mask
;
722 if (data
& 0x01) *bp
|= plane_mask
;
736 } while (mask
& rightMask
);
740 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
741 //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
742 //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
743 //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
744 //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
747 // This algorithm goes from left to right
748 // It stores each 4BPP pixel in an entire byte.
750 vgaWriteScan ( int x
, int y
, int w
, void *b
)
754 unsigned char init_mask
;
755 volatile unsigned char dummy
;
757 int i
, j
, off
, init_off
= x
&7;
761 ASSIGNMK4(x
, y
, init_mask
)
762 byte_per_line
= SCREEN_X
>> 3;
764 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
765 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
766 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
767 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
768 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
770 //DbgPrint("vgaWriteScan(%i,%i,%i...)\n",x,y,w);
771 for ( j
= 0; j
< 8; j
++ )
773 unsigned int mask
= 0x80 >> j
;
774 //DbgPrint("j=%i\n",j);
775 WRITE_PORT_UCHAR ( (PUCHAR
)GRA_D
, (unsigned char)mask
);
782 //DbgPrint("(%i)",i);
796 void DFB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int bw
)
798 // This algorithm goes from left to right, and inside that loop, top to bottom.
799 // It also stores each 4BPP pixel in an entire byte.
801 unsigned char *vp
, *vpY
, *vpP
;
802 unsigned char data
, mask
, maskP
;
803 unsigned char *bp
, *bpY
;
804 unsigned char plane_mask
;
805 int byte_per_line
= SCREEN_X
>> 3;
809 ASSIGNMK4(x
, y
, maskP
)
811 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // read mode 0
812 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
813 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04); // read map select
823 for ( plane
=0, plane_mask
=1; plane
< 4; plane
++, plane_mask
<<=1 )
825 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
); // read map select
828 for ( j
=h
; j
>0; j
-- )
842 } while (mask
& leftMask
);
847 for (i
=byteCounter
; i
>0; i
--)
850 if (data
& 0x80) *bp
|= plane_mask
;
852 if (data
& 0x40) *bp
|= plane_mask
;
854 if (data
& 0x20) *bp
|= plane_mask
;
856 if (data
& 0x10) *bp
|= plane_mask
;
858 if (data
& 0x08) *bp
|= plane_mask
;
860 if (data
& 0x04) *bp
|= plane_mask
;
862 if (data
& 0x02) *bp
|= plane_mask
;
864 if (data
& 0x01) *bp
|= plane_mask
;
874 if (data
& mask
) *bp
|= plane_mask
;
877 } while (mask
& rightMask
);
880 vpY
+= byte_per_line
;
884 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
885 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
886 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
887 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
888 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
891 void DFB_BltToVGA(int x
, int y
, int w
, int h
, void *b
, int bw
)
893 // This algorithm goes from left to right, and inside that loop, top to bottom.
894 // It also stores each 4BPP pixel in an entire byte.
896 unsigned char *bp
, *bpX
;
897 unsigned char *vp
, *vpX
;
899 volatile unsigned char dummy
;
905 ASSIGNMK4(x
, y
, mask
)
906 byte_per_line
= SCREEN_X
>> 3;
908 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
909 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
910 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
911 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
912 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
916 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, mask
);
927 if ((mask
>>= 1) == 0)
935 void DFB_BltToVGA_Transparent(int x
, int y
, int w
, int h
, void *b
, int bw
, char Trans
)
937 // This algorithm goes from goes from left to right, and inside that loop, top to bottom.
938 // It also stores each 4BPP pixel in an entire byte.
940 unsigned char *bp
, *bpX
;
941 unsigned char *vp
, *vpX
;
943 volatile unsigned char dummy
;
949 ASSIGNMK4(x
, y
, mask
)
950 byte_per_line
= SCREEN_X
>> 3;
952 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
953 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
954 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
955 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
956 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
960 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, mask
);
974 if ((mask
>>= 1) == 0)
982 void DFB_BltToDIB(int x
, int y
, int w
, int h
, void *b
, int bw
, void *bdib
, int dibw
)
984 // This algorithm converts a DFB into a DIB
985 // WARNING: This algorithm is buggy
987 unsigned char *bp
, *bpX
, *dib
, *dibTmp
;
991 dib
= (unsigned char *)bdib
+ y
* dibw
+ (x
/ 2);
993 for (i
=w
; i
>0; i
--) {
995 // determine the bit shift for the DIB pixel
996 dib_shift
= mod2(w
-i
);
997 if(dib_shift
> 0) dib_shift
= 4;
1001 for (j
=h
; j
>0; j
--) {
1002 *dibTmp
= *bp
<< dib_shift
| *(bp
+ 1);
1007 if(dib_shift
== 0) dib
++;
1012 void DIB_BltToDFB(int x
, int y
, int w
, int h
, void *b
, int bw
, void *bdib
, int dibw
)
1014 // This algorithm converts a DIB into a DFB
1016 unsigned char *bp
, *bpX
, *dib
, *dibTmp
;
1017 int i
, j
, dib_shift
, dib_and
;
1020 dib
= (unsigned char *)bdib
+ y
* dibw
+ (x
/ 2);
1022 for (i
=w
; i
>0; i
--) {
1024 // determine the bit shift for the DIB pixel
1025 dib_shift
= mod2(w
-i
);
1037 for (j
=h
; j
>0; j
--) {
1038 *bp
= (*dibTmp
& dib_and
) >> dib_shift
;
1044 if(dib_shift
== 0) dib
++;