eadf207dd9289d13f6b45a27d1afb1d2c2a05a6c
2 #include <ddk/ntddvdeo.h>
3 #include <ddk/winddi.h>
7 UCHAR PreCalcReverseByte
[256];
15 static ULONG UnpackPixel
[256];
17 static unsigned char leftMask
;
18 static int byteCounter
;
19 static unsigned char rightMask
;
21 #define READ_REGISTER_UCHAR(p) (*((volatile UCHAR *)(p)))
22 #define WRITE_REGISTER_UCHAR(p,c) (*((volatile CHAR *)(p))) = (c)
35 div_t div(int num
, int denom
)
38 if (num
> 0 && denom
< 0) {
44 if (num
< 0 && denom
> 0)
55 /*int mod(int num, int denom)
57 div_t dvt = div(num, denom);
61 BYTE
bytesPerPixel(ULONG Format
)
63 // This function is taken from /subsys/win32k/eng/surface.c
64 // FIXME: GDI bitmaps are supposed to be pixel-packed. Right now if the
65 // pixel size if < 1 byte we expand it to 1 byte for simplicities sake
145 for (j
= 0; j
< 256; j
++)
147 PreCalcReverseByte
[j
] =
148 (((j
>> 0) & 0x1) << 7) |
149 (((j
>> 1) & 0x1) << 6) |
150 (((j
>> 2) & 0x1) << 5) |
151 (((j
>> 3) & 0x1) << 4) |
152 (((j
>> 4) & 0x1) << 3) |
153 (((j
>> 5) & 0x1) << 2) |
154 (((j
>> 6) & 0x1) << 1) |
155 (((j
>> 7) & 0x1) << 0);
158 for (j
= 0; j
< 256; j
++)
161 (((j
>> 0) & 0x1) << 4) |
162 (((j
>> 1) & 0x1) << 0) |
163 (((j
>> 2) & 0x1) << 12) |
164 (((j
>> 3) & 0x1) << 8) |
165 (((j
>> 4) & 0x1) << 20) |
166 (((j
>> 5) & 0x1) << 16) |
167 (((j
>> 6) & 0x1) << 28) |
168 (((j
>> 7) & 0x1) << 24);
173 get_masks(int x
, int w
)
177 leftMask
= rightMask
= 0;
183 rightMask
= (unsigned char)(0xff00 >> tmp
);
188 byteCounter
-= (8 - tmp
);
189 leftMask
= (0xff >> tmp
);
192 if (byteCounter
< 0) {
193 leftMask
&= rightMask
;
200 VOID
vgaPutPixel(INT x
, INT y
, UCHAR c
)
205 offset
= xconv
[x
]+y80
[y
];
207 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08);
208 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,maskbit
[x
]);
210 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
211 WRITE_REGISTER_UCHAR(vidmem
+ offset
, c
);
214 VOID
vgaPutByte(INT x
, INT y
, UCHAR c
)
218 offset
= xconv
[x
]+y80
[y
];
220 // Set the write mode
221 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08);
222 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,0xff);
224 WRITE_REGISTER_UCHAR(vidmem
+ offset
, c
);
227 VOID
vgaGetByte(ULONG offset
,
231 WRITE_PORT_USHORT((PUSHORT
)GRA_I
, 0x0304);
232 *i
= READ_REGISTER_UCHAR(vidmem
+ offset
);
233 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
234 *r
= READ_REGISTER_UCHAR(vidmem
+ offset
);
235 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x01);
236 *g
= READ_REGISTER_UCHAR(vidmem
+ offset
);
237 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
238 *b
= READ_REGISTER_UCHAR(vidmem
+ offset
);
241 INT
vgaGetPixel(INT x
, INT y
)
243 UCHAR mask
, b
, g
, r
, i
;
246 offset
= xconv
[x
]+y80
[y
];
247 vgaGetByte(offset
, &b
, &g
, &r
, &i
);
261 return(b
+2*g
+4*r
+8*i
);
264 BOOL
vgaHLine(INT x
, INT y
, INT len
, UCHAR c
)
268 ULONG orgpre1
, orgx
, midpre1
;
269 ULONG ileftpix
, imidpix
, irightpix
;
275 for (i = x; i < x+len; i++ )
276 vgaPutPixel ( i, y, c );
281 // Calculate the left mask pixels, middle bytes and right mask pixel
282 ileftpix
= 7 - mod8(x
-1);
283 irightpix
= mod8(x
+len
);
284 imidpix
= (len
-ileftpix
-irightpix
) / 8;
286 pre1
= xconv
[(x
-1)&~7] + y80
[y
];
289 // check for overlap ( very short line )
290 if ( (ileftpix
+irightpix
) > len
)
292 int mask
= startmasks
[ileftpix
] & endmasks
[irightpix
];
294 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask
295 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,mask
);
297 a
= READ_REGISTER_UCHAR(vidmem
+ pre1
);
298 WRITE_REGISTER_UCHAR(vidmem
+ pre1
, c
);
307 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask
308 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,startmasks
[ileftpix
]);
310 a
= READ_REGISTER_UCHAR(vidmem
+ pre1
);
311 WRITE_REGISTER_UCHAR(vidmem
+ pre1
, c
);
313 // Prepare new x for the middle
319 midpre1
= xconv
[x
] + y80
[y
];
321 // Set mask to all pixels in byte
322 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08);
323 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0xff);
324 memset(vidmem
+midpre1
, c
, imidpix
); // write middle pixels, no need to read in latch because of the width
329 x
= orgx
+ len
- irightpix
;
330 pre1
= xconv
[x
] + y80
[y
];
332 // Write right pixels
333 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask bits
334 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, endmasks
[irightpix
]);
335 a
= READ_REGISTER_UCHAR(vidmem
+ pre1
);
336 WRITE_REGISTER_UCHAR(vidmem
+ pre1
, c
);
342 BOOL
vgaVLine(INT x
, INT y
, INT len
, UCHAR c
)
347 offset
= xconv
[x
]+y80
[y
];
350 vgaSetBitMaskRegister ( maskbit
[x
] );
352 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
,0x08); // set the mask
353 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
,maskbit
[x
]);
356 for(i
=y
; i
<y
+len
; i
++)
358 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
359 WRITE_REGISTER_UCHAR(vidmem
+ offset
, c
);
366 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
368 BOOL
VGADDIIntersectRect(PRECTL prcDst
, PRECTL prcSrc1
, PRECTL prcSrc2
)
370 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
371 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
373 if (prcDst
->left
< prcDst
->right
) {
374 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
375 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
377 if (prcDst
->top
< prcDst
->bottom
)
388 void DIB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int Dest_lDelta
)
392 ULONG shift
= x
- (x
& ~0x7);
393 UCHAR pixel
, nextpixel
;
396 ULONG stride
= w
>> 3;
398 /* Calculate the number of rightmost bytes not in a dword block. */
409 /* Reset the destination. */
410 for (j
= 0; j
< h
; j
++)
412 memset((PVOID
)((ULONG_PTR
)b
+ (j
* Dest_lDelta
)), 0, abs(Dest_lDelta
));
415 for (plane
= 0; plane
< 4; plane
++)
419 /* Select the plane we are reading in this iteration. */
420 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04);
421 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
);
423 for (j
= 0; j
< h
; j
++)
425 PULONG destline
= (PULONG
)dest
;
426 PUCHAR src
= vidmem
+ (y
+ j
) * SCREEN_STRIDE
+ left
;
427 /* Read the data for one plane for an eight aligned pixel block. */
428 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
)];
429 for (i
= 0; i
< stride
; i
++, src
++, destline
++)
431 /* Form the data for one plane for an aligned block in the destination. */
435 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
+ 1)];
436 pixel
|= (nextpixel
<< (8 - shift
));
438 /* Expand the plane data to 'chunky' format and store. */
439 *destline
|= (UnpackPixel
[pixel
] << plane
);
441 /* Handle any pixels not falling into a full block. */
446 /* Form the data for a complete block. */
450 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
+ 1)];
451 pixel
|= (nextpixel
<< (8 - shift
));
453 row
= UnpackPixel
[pixel
] << plane
;
455 /* Store the data for each pixel in the destination. */
456 for (i
= 0; i
< rightcount
; i
++)
458 ((PUCHAR
)destline
)[i
] |= (row
& 0xFF);
467 for (j
= 0; j
< h
; j
++)
469 for (i
= 0; i
< w
; i
+=2)
472 ULONG mask
= (i
< (w
- 1)) ? 0xFF : 0xF0;
474 c1
= (vgaGetPixel(x
+ i
, y
+ j
) << 4) | (vgaGetPixel(x
+ i
+ 1, y
+ j
));
475 c2
= ((PUCHAR
)b
)[(j
* Dest_lDelta
) + (i
>> 1)];
476 if ((c1
& mask
) != (c2
& mask
))
478 __asm__("int $3\n\t" : /* no outputs */ : /* no inputs */);
482 #endif /* VGA_VERIFY */
486 void DIB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int Dest_lDelta
)
487 // DIB blt from the VGA.
488 // For now we just do slow reads -- pixel by pixel, packing each one into the correct 4BPP format.
490 PBYTE pb
= b
, opb
= b
;
491 BOOLEAN edgePixel
= FALSE
;
497 // Check if the width is odd
506 for (i
=x
; i
<x2
; i
+=2)
508 b1
= vgaGetPixel(i
, j
);
509 b2
= vgaGetPixel(i
+1, j
);
510 *pb
= b2
| (b1
<< 4);
514 if(edgePixel
== TRUE
)
516 b1
= vgaGetPixel(x2
, j
);
521 opb
+= Dest_lDelta
; // new test code
522 pb
= opb
; // new test code
527 /* DIB blt to the VGA. */
528 void DIB_BltToVGA(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, int StartMod
)
537 for (i
= x
; i
< x2
; i
++)
540 offset
= xconv
[i
] + y80
[y
];
542 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // set the mask
543 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, maskbit
[i
]);
545 if (StartMod
== ((i
- x
) % 2))
547 for (j
= y
; j
< y2
; j
++)
549 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
550 WRITE_REGISTER_UCHAR(vidmem
+ offset
, (*pb
& 0xf0) >> 4);
557 for (j
= y
; j
< y2
; j
++)
559 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
560 WRITE_REGISTER_UCHAR(vidmem
+ offset
, *pb
& 0x0f);
566 if (StartMod
!= ((i
- x
) % 2))
574 /* DIB blt to the VGA. */
575 void DIB_BltToVGAWithXlate(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, XLATEOBJ
* Xlate
)
584 for (i
= x
; i
< x2
; i
++)
587 offset
= xconv
[i
] + y80
[y
];
589 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // set the mask
590 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, maskbit
[i
]);
592 if (0 == ((i
- x
) % 2))
594 for (j
= y
; j
< y2
; j
++)
596 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
597 WRITE_REGISTER_UCHAR(vidmem
+ offset
, XLATEOBJ_iXlate(Xlate
, (*pb
& 0xf0) >> 4));
604 for (j
= y
; j
< y2
; j
++)
606 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
607 WRITE_REGISTER_UCHAR(vidmem
+ offset
, XLATEOBJ_iXlate(Xlate
, *pb
& 0x0f));
613 if (0 != ((i
- x
) % 2))
620 void DIB_TransparentBltToVGA(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, ULONG trans
)
622 // DIB blt to the VGA.
623 // For now we just do slow writes -- pixel by pixel, packing each one into the correct 4BPP format.
625 PBYTE pb
= b
, opb
= b
;
626 BOOLEAN edgePixel
= FALSE
;
632 // Check if the width is odd
641 for (i
=x
; i
<x2
; i
+=2)
643 b1
= (*pb
& 0xf0) >> 4;
645 if(b1
!= trans
) vgaPutPixel(i
, j
, b1
);
646 if(b2
!= trans
) vgaPutPixel(i
+1, j
, b2
);
650 if(edgePixel
== TRUE
)
653 if(b1
!= trans
) vgaPutPixel(x2
, j
, b1
);
657 opb
+= Source_lDelta
;
658 pb
= opb
; // new test code
663 // This algorithm goes from left to right, storing each 4BPP pixel
664 // in an entire byte.
666 vgaReadScan ( int x
, int y
, int w
, void *b
)
668 unsigned char *vp
, *vpP
;
669 unsigned char data
, mask
, maskP
;
671 unsigned char plane_mask
;
675 ASSIGNMK4(x
, y
, maskP
)
677 WRITE_PORT_USHORT((PUSHORT
)GRA_I
, 0x0005); // read mode 0
678 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04); // read map select
682 for ( plane
=0, plane_mask
=1; plane
< 4; plane
++, plane_mask
<<=1 )
684 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
); // read map select
698 } while (mask
& leftMask
);
703 for (i
=byteCounter
; i
>0; i
--)
706 if (data
& 0x80) *bp
|= plane_mask
;
708 if (data
& 0x40) *bp
|= plane_mask
;
710 if (data
& 0x20) *bp
|= plane_mask
;
712 if (data
& 0x10) *bp
|= plane_mask
;
714 if (data
& 0x08) *bp
|= plane_mask
;
716 if (data
& 0x04) *bp
|= plane_mask
;
718 if (data
& 0x02) *bp
|= plane_mask
;
720 if (data
& 0x01) *bp
|= plane_mask
;
734 } while (mask
& rightMask
);
738 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
739 //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
740 //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
741 //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
742 //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
745 // This algorithm goes from left to right
746 // It stores each 4BPP pixel in an entire byte.
748 vgaWriteScan ( int x
, int y
, int w
, void *b
)
752 unsigned char init_mask
;
753 volatile unsigned char dummy
;
755 int i
, j
, off
, init_off
= x
&7;
759 ASSIGNMK4(x
, y
, init_mask
)
760 byte_per_line
= SCREEN_X
>> 3;
762 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
763 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
764 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
765 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
766 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
768 //DbgPrint("vgaWriteScan(%i,%i,%i...)\n",x,y,w);
769 for ( j
= 0; j
< 8; j
++ )
771 unsigned int mask
= 0x80 >> j
;
772 //DbgPrint("j=%i\n",j);
773 WRITE_PORT_UCHAR ( (PUCHAR
)GRA_D
, (unsigned char)mask
);
780 //DbgPrint("(%i)",i);
794 void DFB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int bw
)
796 // This algorithm goes from left to right, and inside that loop, top to bottom.
797 // It also stores each 4BPP pixel in an entire byte.
799 unsigned char *vp
, *vpY
, *vpP
;
800 unsigned char data
, mask
, maskP
;
801 unsigned char *bp
, *bpY
;
802 unsigned char plane_mask
;
803 int byte_per_line
= SCREEN_X
>> 3;
807 ASSIGNMK4(x
, y
, maskP
)
809 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // read mode 0
810 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
811 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04); // read map select
821 for ( plane
=0, plane_mask
=1; plane
< 4; plane
++, plane_mask
<<=1 )
823 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
); // read map select
826 for ( j
=h
; j
>0; j
-- )
840 } while (mask
& leftMask
);
845 for (i
=byteCounter
; i
>0; i
--)
848 if (data
& 0x80) *bp
|= plane_mask
;
850 if (data
& 0x40) *bp
|= plane_mask
;
852 if (data
& 0x20) *bp
|= plane_mask
;
854 if (data
& 0x10) *bp
|= plane_mask
;
856 if (data
& 0x08) *bp
|= plane_mask
;
858 if (data
& 0x04) *bp
|= plane_mask
;
860 if (data
& 0x02) *bp
|= plane_mask
;
862 if (data
& 0x01) *bp
|= plane_mask
;
872 if (data
& mask
) *bp
|= plane_mask
;
875 } while (mask
& rightMask
);
878 vpY
+= byte_per_line
;
882 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
883 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
884 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
885 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
886 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
889 void DFB_BltToVGA(int x
, int y
, int w
, int h
, void *b
, int bw
)
891 // This algorithm goes from left to right, and inside that loop, top to bottom.
892 // It also stores each 4BPP pixel in an entire byte.
894 unsigned char *bp
, *bpX
;
895 unsigned char *vp
, *vpX
;
897 volatile unsigned char dummy
;
903 ASSIGNMK4(x
, y
, mask
)
904 byte_per_line
= SCREEN_X
>> 3;
906 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
907 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
908 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
909 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
910 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
914 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, mask
);
925 if ((mask
>>= 1) == 0)
933 void DFB_BltToVGA_Transparent(int x
, int y
, int w
, int h
, void *b
, int bw
, char Trans
)
935 // This algorithm goes from goes from left to right, and inside that loop, top to bottom.
936 // It also stores each 4BPP pixel in an entire byte.
938 unsigned char *bp
, *bpX
;
939 unsigned char *vp
, *vpX
;
941 volatile unsigned char dummy
;
947 ASSIGNMK4(x
, y
, mask
)
948 byte_per_line
= SCREEN_X
>> 3;
950 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
951 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
952 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
953 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
954 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
958 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, mask
);
972 if ((mask
>>= 1) == 0)
980 void DFB_BltToDIB(int x
, int y
, int w
, int h
, void *b
, int bw
, void *bdib
, int dibw
)
982 // This algorithm converts a DFB into a DIB
983 // WARNING: This algorithm is buggy
985 unsigned char *bp
, *bpX
, *dib
, *dibTmp
;
989 dib
= (unsigned char *)bdib
+ y
* dibw
+ (x
/ 2);
991 for (i
=w
; i
>0; i
--) {
993 // determine the bit shift for the DIB pixel
994 dib_shift
= mod2(w
-i
);
995 if(dib_shift
> 0) dib_shift
= 4;
999 for (j
=h
; j
>0; j
--) {
1000 *dibTmp
= *bp
<< dib_shift
| *(bp
+ 1);
1005 if(dib_shift
== 0) dib
++;
1010 void DIB_BltToDFB(int x
, int y
, int w
, int h
, void *b
, int bw
, void *bdib
, int dibw
)
1012 // This algorithm converts a DIB into a DFB
1014 unsigned char *bp
, *bpX
, *dib
, *dibTmp
;
1015 int i
, j
, dib_shift
, dib_and
;
1018 dib
= (unsigned char *)bdib
+ y
* dibw
+ (x
/ 2);
1020 for (i
=w
; i
>0; i
--) {
1022 // determine the bit shift for the DIB pixel
1023 dib_shift
= mod2(w
-i
);
1035 for (j
=h
; j
>0; j
--) {
1036 *bp
= (*dibTmp
& dib_and
) >> dib_shift
;
1042 if(dib_shift
== 0) dib
++;