1 #include <ddk/ntddvdeo.h>
2 #include <ddk/winddi.h>
3 #include <ntos/minmax.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) (*((PUCHAR)(p)))
22 #define WRITE_REGISTER_UCHAR(p,c) (*((PCHAR)(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 memset(b
, 0, h
* Dest_lDelta
);
412 for (plane
= 0; plane
< 4; plane
++)
416 /* Select the plane we are reading in this iteration. */
417 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04);
418 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
);
420 for (j
= 0; j
< h
; j
++)
422 PULONG destline
= (PULONG
)dest
;
423 PUCHAR src
= vidmem
+ (y
+ j
) * SCREEN_STRIDE
+ left
;
424 /* Read the data for one plane for an eight aligned pixel block. */
425 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
)];
426 for (i
= 0; i
< stride
; i
++, src
++, destline
++)
428 /* Form the data for one plane for an aligned block in the destination. */
432 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
+ 1)];
433 pixel
|= (nextpixel
<< (8 - shift
));
435 /* Expand the plane data to 'chunky' format and store. */
436 *destline
|= (UnpackPixel
[pixel
] << plane
);
438 /* Handle any pixels not falling into a full block. */
443 /* Form the data for a complete block. */
447 nextpixel
= PreCalcReverseByte
[READ_REGISTER_UCHAR(src
+ 1)];
448 pixel
|= (nextpixel
<< (8 - shift
));
450 row
= UnpackPixel
[pixel
] << plane
;
452 /* Store the data for each pixel in the destination. */
453 for (i
= 0; i
< rightcount
; i
++)
455 ((PUCHAR
)destline
)[i
] |= (row
& 0xFF);
464 for (j
= 0; j
< h
; j
++)
466 for (i
= 0; i
< w
; i
+=2)
469 ULONG mask
= (i
< (w
- 1)) ? 0xFF : 0xF0;
471 c1
= (vgaGetPixel(x
+ i
, y
+ j
) << 4) | (vgaGetPixel(x
+ i
+ 1, y
+ j
));
472 c2
= ((PUCHAR
)b
)[(j
* Dest_lDelta
) + (i
>> 1)];
473 if ((c1
& mask
) != (c2
& mask
))
475 __asm__("int $3\n\t" : /* no outputs */ : /* no inputs */);
479 #endif /* VGA_VERIFY */
483 void DIB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int Dest_lDelta
)
484 // DIB blt from the VGA.
485 // For now we just do slow reads -- pixel by pixel, packing each one into the correct 4BPP format.
487 PBYTE pb
= b
, opb
= b
;
488 BOOLEAN edgePixel
= FALSE
;
494 // Check if the width is odd
503 for (i
=x
; i
<x2
; i
+=2)
505 b1
= vgaGetPixel(i
, j
);
506 b2
= vgaGetPixel(i
+1, j
);
507 *pb
= b2
| (b1
<< 4);
511 if(edgePixel
== TRUE
)
513 b1
= vgaGetPixel(x2
, j
);
518 opb
+= Dest_lDelta
; // new test code
519 pb
= opb
; // new test code
524 /* DIB blt to the VGA. */
525 void DIB_BltToVGA(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, int StartMod
)
534 for (i
= x
; i
< x2
; i
++)
537 offset
= xconv
[i
] + y80
[y
];
539 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // set the mask
540 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, maskbit
[i
]);
542 if (StartMod
== ((i
- x
) % 2))
544 for (j
= y
; j
< y2
; j
++)
546 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
547 WRITE_REGISTER_UCHAR(vidmem
+ offset
, (*pb
& 0xf0) >> 4);
554 for (j
= y
; j
< y2
; j
++)
556 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
557 WRITE_REGISTER_UCHAR(vidmem
+ offset
, *pb
& 0x0f);
563 if (StartMod
!= ((i
- x
) % 2))
571 /* DIB blt to the VGA. */
572 void DIB_BltToVGAWithXlate(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, XLATEOBJ
* Xlate
)
581 for (i
= x
; i
< x2
; i
++)
584 offset
= xconv
[i
] + y80
[y
];
586 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // set the mask
587 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, maskbit
[i
]);
589 if (0 == ((i
- x
) % 2))
591 for (j
= y
; j
< y2
; j
++)
593 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
594 WRITE_REGISTER_UCHAR(vidmem
+ offset
, XLATEOBJ_iXlate(Xlate
, (*pb
& 0xf0) >> 4));
601 for (j
= y
; j
< y2
; j
++)
603 a
= READ_REGISTER_UCHAR(vidmem
+ offset
);
604 WRITE_REGISTER_UCHAR(vidmem
+ offset
, XLATEOBJ_iXlate(Xlate
, *pb
& 0x0f));
610 if (0 != ((i
- x
) % 2))
617 void DIB_TransparentBltToVGA(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, ULONG trans
)
619 // DIB blt to the VGA.
620 // For now we just do slow writes -- pixel by pixel, packing each one into the correct 4BPP format.
622 PBYTE pb
= b
, opb
= b
;
623 BOOLEAN edgePixel
= FALSE
;
629 // Check if the width is odd
638 for (i
=x
; i
<x2
; i
+=2)
640 b1
= (*pb
& 0xf0) >> 4;
642 if(b1
!= trans
) vgaPutPixel(i
, j
, b1
);
643 if(b2
!= trans
) vgaPutPixel(i
+1, j
, b2
);
647 if(edgePixel
== TRUE
)
650 if(b1
!= trans
) vgaPutPixel(x2
, j
, b1
);
654 opb
+= Source_lDelta
;
655 pb
= opb
; // new test code
660 // This algorithm goes from left to right, storing each 4BPP pixel
661 // in an entire byte.
663 vgaReadScan ( int x
, int y
, int w
, void *b
)
665 unsigned char *vp
, *vpP
;
666 unsigned char data
, mask
, maskP
;
668 unsigned char plane_mask
;
672 ASSIGNMK4(x
, y
, maskP
)
674 WRITE_PORT_USHORT((PUSHORT
)GRA_I
, 0x0005); // read mode 0
675 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04); // read map select
679 for ( plane
=0, plane_mask
=1; plane
< 4; plane
++, plane_mask
<<=1 )
681 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
); // read map select
695 } while (mask
& leftMask
);
700 for (i
=byteCounter
; i
>0; i
--)
703 if (data
& 0x80) *bp
|= plane_mask
;
705 if (data
& 0x40) *bp
|= plane_mask
;
707 if (data
& 0x20) *bp
|= plane_mask
;
709 if (data
& 0x10) *bp
|= plane_mask
;
711 if (data
& 0x08) *bp
|= plane_mask
;
713 if (data
& 0x04) *bp
|= plane_mask
;
715 if (data
& 0x02) *bp
|= plane_mask
;
717 if (data
& 0x01) *bp
|= plane_mask
;
731 } while (mask
& rightMask
);
735 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
736 //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
737 //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
738 //WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
739 //WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
742 // This algorithm goes from left to right
743 // It stores each 4BPP pixel in an entire byte.
745 vgaWriteScan ( int x
, int y
, int w
, void *b
)
749 unsigned char init_mask
;
750 volatile unsigned char dummy
;
752 int i
, j
, off
, init_off
= x
&7;
756 ASSIGNMK4(x
, y
, init_mask
)
757 byte_per_line
= SCREEN_X
>> 3;
759 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
760 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
761 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
762 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
763 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
765 //DbgPrint("vgaWriteScan(%i,%i,%i...)\n",x,y,w);
766 for ( j
= 0; j
< 8; j
++ )
768 unsigned int mask
= 0x80 >> j
;
769 //DbgPrint("j=%i\n",j);
770 WRITE_PORT_UCHAR ( (PUCHAR
)GRA_D
, (unsigned char)mask
);
777 //DbgPrint("(%i)",i);
791 void DFB_BltFromVGA(int x
, int y
, int w
, int h
, void *b
, int bw
)
793 // This algorithm goes from left to right, and inside that loop, top to bottom.
794 // It also stores each 4BPP pixel in an entire byte.
796 unsigned char *vp
, *vpY
, *vpP
;
797 unsigned char data
, mask
, maskP
;
798 unsigned char *bp
, *bpY
;
799 unsigned char plane_mask
;
800 int byte_per_line
= SCREEN_X
>> 3;
804 ASSIGNMK4(x
, y
, maskP
)
806 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // read mode 0
807 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
808 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x04); // read map select
818 for ( plane
=0, plane_mask
=1; plane
< 4; plane
++, plane_mask
<<=1 )
820 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, plane
); // read map select
823 for ( j
=h
; j
>0; j
-- )
837 } while (mask
& leftMask
);
842 for (i
=byteCounter
; i
>0; i
--)
845 if (data
& 0x80) *bp
|= plane_mask
;
847 if (data
& 0x40) *bp
|= plane_mask
;
849 if (data
& 0x20) *bp
|= plane_mask
;
851 if (data
& 0x10) *bp
|= plane_mask
;
853 if (data
& 0x08) *bp
|= plane_mask
;
855 if (data
& 0x04) *bp
|= plane_mask
;
857 if (data
& 0x02) *bp
|= plane_mask
;
859 if (data
& 0x01) *bp
|= plane_mask
;
869 if (data
& mask
) *bp
|= plane_mask
;
872 } while (mask
& rightMask
);
875 vpY
+= byte_per_line
;
879 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
880 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
881 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
882 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
883 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
886 void DFB_BltToVGA(int x
, int y
, int w
, int h
, void *b
, int bw
)
888 // This algorithm goes from left to right, and inside that loop, top to bottom.
889 // It also stores each 4BPP pixel in an entire byte.
891 unsigned char *bp
, *bpX
;
892 unsigned char *vp
, *vpX
;
894 volatile unsigned char dummy
;
900 ASSIGNMK4(x
, y
, mask
)
901 byte_per_line
= SCREEN_X
>> 3;
903 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
904 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
905 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
906 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
907 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
911 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, mask
);
922 if ((mask
>>= 1) == 0)
930 void DFB_BltToVGA_Transparent(int x
, int y
, int w
, int h
, void *b
, int bw
, char Trans
)
932 // This algorithm goes from goes from left to right, and inside that loop, top to bottom.
933 // It also stores each 4BPP pixel in an entire byte.
935 unsigned char *bp
, *bpX
;
936 unsigned char *vp
, *vpX
;
938 volatile unsigned char dummy
;
944 ASSIGNMK4(x
, y
, mask
)
945 byte_per_line
= SCREEN_X
>> 3;
947 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05); // write mode 2
948 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
949 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03); // replace
950 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
951 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08); // bit mask
955 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, mask
);
969 if ((mask
>>= 1) == 0)
977 void DFB_BltToDIB(int x
, int y
, int w
, int h
, void *b
, int bw
, void *bdib
, int dibw
)
979 // This algorithm converts a DFB into a DIB
980 // WARNING: This algorithm is buggy
982 unsigned char *bp
, *bpX
, *dib
, *dibTmp
;
986 dib
= bdib
+ y
* dibw
+ (x
/ 2);
988 for (i
=w
; i
>0; i
--) {
990 // determine the bit shift for the DIB pixel
991 dib_shift
= mod2(w
-i
);
992 if(dib_shift
> 0) dib_shift
= 4;
996 for (j
=h
; j
>0; j
--) {
997 *dibTmp
= *bp
<< dib_shift
| *(bp
+ 1);
1002 if(dib_shift
== 0) dib
++;
1007 void DIB_BltToDFB(int x
, int y
, int w
, int h
, void *b
, int bw
, void *bdib
, int dibw
)
1009 // This algorithm converts a DIB into a DFB
1011 unsigned char *bp
, *bpX
, *dib
, *dibTmp
;
1012 int i
, j
, dib_shift
, dib_and
;
1015 dib
= bdib
+ y
* dibw
+ (x
/ 2);
1017 for (i
=w
; i
>0; i
--) {
1019 // determine the bit shift for the DIB pixel
1020 dib_shift
= mod2(w
-i
);
1032 for (j
=h
; j
>0; j
--) {
1033 *bp
= (*dibTmp
& dib_and
) >> dib_shift
;
1039 if(dib_shift
== 0) dib
++;