2 #include <ddk/ntddvid.h>
3 #include <ddk/winddi.h>
4 #include <ntos/minmax.h>
7 UCHAR PreCalcReverseByte[256];
16 static unsigned char saved_SEQ_mask; /* 0x02 */
17 static unsigned char saved_GC_eSR; /* 0x01 */
18 static unsigned char saved_GC_fun; /* 0x03 */
19 static unsigned char saved_GC_rmap; /* 0x04 */
20 static unsigned char saved_GC_mode; /* 0x05 */
21 static unsigned char saved_GC_mask; /* 0x08 */
22 static unsigned char leftMask;
23 static int byteCounter;
24 static unsigned char rightMask;
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
73 if((Format==BMF_4BPP) || (Format==BMF_4RLE))
77 if((Format==BMF_8BPP) || (Format==BMF_8RLE))
150 for (j = 0; j < 256; j++)
152 PreCalcReverseByte[j] =
153 (((j >> 0) & 0x1) << 7) |
154 (((j >> 1) & 0x1) << 6) |
155 (((j >> 2) & 0x1) << 5) |
156 (((j >> 3) & 0x1) << 4) |
157 (((j >> 4) & 0x1) << 3) |
158 (((j >> 5) & 0x1) << 2) |
159 (((j >> 6) & 0x1) << 1) |
160 (((j >> 7) & 0x1) << 0);
165 get_masks(int x, int w)
169 leftMask = rightMask = 0;
175 rightMask = (unsigned char)(0xff00 >> tmp);
180 byteCounter -= (8 - tmp);
181 leftMask = (0xff >> tmp);
184 if (byteCounter < 0) {
185 leftMask &= rightMask;
192 VOID vgaPutPixel(INT x, INT y, UCHAR c)
197 offset = xconv[x]+y80[y];
199 WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08);
200 WRITE_PORT_UCHAR((PUCHAR)0x3cf,maskbit[x]);
202 a = READ_REGISTER_UCHAR(vidmem + offset);
203 WRITE_REGISTER_UCHAR(vidmem + offset, c);
206 VOID vgaPutByte(INT x, INT y, UCHAR c)
210 offset = xconv[x]+y80[y];
212 // Set the write mode
213 WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08);
214 WRITE_PORT_UCHAR((PUCHAR)0x3cf,0xff);
216 WRITE_REGISTER_UCHAR(vidmem + offset, c);
219 VOID vgaGetByte(ULONG offset,
223 WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0304);
224 *i = READ_REGISTER_UCHAR(vidmem + offset);
225 WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0204);
226 *r = READ_REGISTER_UCHAR(vidmem + offset);
227 WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0104);
228 *g = READ_REGISTER_UCHAR(vidmem + offset);
229 WRITE_PORT_USHORT((PUSHORT)0x03ce, 0x0004);
230 *b = READ_REGISTER_UCHAR(vidmem + offset);
233 INT vgaGetPixel(INT x, INT y)
235 UCHAR mask, b, g, r, i;
238 offset = xconv[x]+y80[y];
239 vgaGetByte(offset, &b, &g, &r, &i);
253 return(b+2*g+4*r+8*i);
256 BOOL vgaHLine(INT x, INT y, INT len, UCHAR c)
260 ULONG orgpre1, orgx, midpre1;
261 ULONG ileftpix, imidpix, irightpix;
267 for (i=x; i<x+len; i++)
268 vgaPutPixel(i, y, c);
273 // Calculate the left mask pixels, middle bytes and right mask pixel
274 ileftpix = 8-mod(x, 8);
275 irightpix = mod(x+len, 8);
276 imidpix = (len-ileftpix-irightpix) / 8;
284 pre1=xconv[x-(8-ileftpix)]+y80[y];
291 WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // set the mask
292 WRITE_PORT_UCHAR((PUCHAR)0x3cf,startmasks[ileftpix]);
294 a = READ_REGISTER_UCHAR(vidmem + pre1);
295 WRITE_REGISTER_UCHAR(vidmem + pre1, c);
297 // Prepare new x for the middle
303 midpre1=xconv[x]+y80[y];
305 // Set mask to all pixels in byte
306 WRITE_PORT_UCHAR((PUCHAR)0x3ce, 0x08);
307 WRITE_PORT_UCHAR((PUCHAR)0x3cf, 0xff);
308 memset(vidmem+midpre1, c, imidpix); // write middle pixels, no need to read in latch because of the width
313 x=orgx+len-irightpix;
315 for(i=x; i<x+irightpix; i++)
317 vgaPutPixel(i, y, c);
320 /* pre1=xconv[x]+y80[y];
322 // Write right pixels
323 WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // set the mask bits
324 WRITE_PORT_UCHAR((PUCHAR)0x3cf, endmasks[irightpix]);
326 a = READ_REGISTER_UCHAR(vidmem + pre1);
327 WRITE_REGISTER_UCHAR(vidmem + pre1, c); */
333 BOOL vgaVLine(INT x, INT y, INT len, UCHAR c)
338 offset = xconv[x]+y80[y];
340 WRITE_PORT_UCHAR((PUCHAR)0x3ce,0x08); // set the mask
341 WRITE_PORT_UCHAR((PUCHAR)0x3cf,maskbit[x]);
343 for(i=y; i<y+len; i++)
345 a = READ_REGISTER_UCHAR(vidmem + offset);
346 WRITE_REGISTER_UCHAR(vidmem + offset, c);
353 static const RECTL rclEmpty = { 0, 0, 0, 0 };
355 BOOL VGADDIIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
357 prcDst->left = max(prcSrc1->left, prcSrc2->left);
358 prcDst->right = min(prcSrc1->right, prcSrc2->right);
360 if (prcDst->left < prcDst->right) {
361 prcDst->top = max(prcSrc1->top, prcSrc2->top);
362 prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
364 if (prcDst->top < prcDst->bottom)
375 void DIB_BltFromVGA(int x, int y, int w, int h, void *b, int Dest_lDelta)
377 // DIB blt from the VGA.
378 // For now we just do slow reads -- pixel by pixel, packing each one into the correct 4BPP format.
380 PBYTE pb = b, opb = b;
381 BOOLEAN edgePixel = FALSE;
387 // Check if the width is odd
396 for (i=x; i<x2; i+=2)
398 b1 = vgaGetPixel(i, j);
399 b2 = vgaGetPixel(i+1, j);
400 *pb = b2 | (b1 << 4);
404 if(edgePixel == TRUE)
406 b1 = vgaGetPixel(x2, j);
411 opb += Dest_lDelta; // new test code
412 pb = opb; // new test code
416 void DIB_BltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta)
418 // DIB blt to the VGA.
419 // For now we just do slow writes -- pixel by pixel, packing each one into the correct 4BPP format.
421 PBYTE pb = b, opb = b;
422 BOOLEAN edgePixel = FALSE;
428 // Check if the width is odd
437 for (i=x; i<x2; i+=2)
439 b1 = (*pb & 0xf0) >> 4;
441 vgaPutPixel(i, j, b1);
442 vgaPutPixel(i+1, j, b2);
446 if(edgePixel == TRUE)
449 vgaPutPixel(x2, j, b1);
453 opb += Source_lDelta;
460 void DIB_TransparentBltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, ULONG trans)
462 // DIB blt to the VGA.
463 // For now we just do slow writes -- pixel by pixel, packing each one into the correct 4BPP format.
465 PBYTE pb = b, opb = b;
466 BOOLEAN edgePixel = FALSE;
472 // Check if the width is odd
481 for (i=x; i<x2; i+=2)
483 b1 = (*pb & 0xf0) >> 4;
485 if(b1 != trans) vgaPutPixel(i, j, b1);
486 if(b2 != trans) vgaPutPixel(i+1, j, b2);
490 if(edgePixel == TRUE)
493 if(b1 != trans) vgaPutPixel(x2, j, b1);
497 opb += Source_lDelta;
498 pb = opb; // new test code
503 void DFB_BltFromVGA(int x, int y, int w, int h, void *b, int bw)
505 // This algorithm goes from goes from left to right, and inside that loop, top to bottom.
506 // It also stores each 4BPP pixel in an entire byte.
508 unsigned char *vp, *vpY, *vpP;
509 unsigned char data, mask, maskP;
510 unsigned char *bp, *bpY;
511 unsigned char plane_mask;
512 int byte_per_line = SCREEN_X >> 3;
516 ASSIGNMK4(x, y, maskP)
518 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // read mode 0
519 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
520 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04); // read map select
524 for (j=h; j>0; j--) {
529 for (plane=0, plane_mask=1; plane<4; plane++, plane_mask<<=1) {
530 WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane); // read map select
533 for (j=h; j>0; j--) {
540 if (data & mask) *bp |= plane_mask;
543 } while (mask & leftMask);
547 for (i=byteCounter; i>0; i--) {
549 if (data & 0x80) *bp |= plane_mask;
551 if (data & 0x40) *bp |= plane_mask;
553 if (data & 0x20) *bp |= plane_mask;
555 if (data & 0x10) *bp |= plane_mask;
557 if (data & 0x08) *bp |= plane_mask;
559 if (data & 0x04) *bp |= plane_mask;
561 if (data & 0x02) *bp |= plane_mask;
563 if (data & 0x01) *bp |= plane_mask;
571 if (data & mask) *bp |= plane_mask;
574 } while (mask & rightMask);
577 vpY += byte_per_line;
581 // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
582 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
583 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
584 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
585 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
588 void DFB_BltToVGA(int x, int y, int w, int h, void *b, int bw)
590 // This algorithm goes from goes from left to right, and inside that loop, top to bottom.
591 // It also stores each 4BPP pixel in an entire byte.
593 unsigned char *bp, *bpX;
594 unsigned char *vp, *vpX;
596 volatile unsigned char dummy;
602 ASSIGNMK4(x, y, mask)
603 byte_per_line = SCREEN_X >> 3;
605 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
606 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
607 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
608 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
609 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask
611 for (i=w; i>0; i--) {
612 WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask);
615 for (j=h; j>0; j--) {
622 if ((mask >>= 1) == 0) {
629 void DFB_BltToVGA_Transparent(int x, int y, int w, int h, void *b, int bw, char Trans)
631 // This algorithm goes from goes from left to right, and inside that loop, top to bottom.
632 // It also stores each 4BPP pixel in an entire byte.
634 unsigned char *bp, *bpX;
635 unsigned char *vp, *vpX;
637 volatile unsigned char dummy;
643 ASSIGNMK4(x, y, mask)
644 byte_per_line = SCREEN_X >> 3;
646 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05); // write mode 2
647 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
648 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03); // replace
649 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
650 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08); // bit mask
652 for (i=w; i>0; i--) {
653 WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask);
656 for (j=h; j>0; j--) {
666 if ((mask >>= 1) == 0) {
673 void DFB_BltToDIB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw)
675 // This algorithm converts a DFB into a DIB
676 // WARNING: This algorithm is buggy
678 unsigned char *bp, *bpX, *dib, *dibTmp;
682 dib = bdib + y * dibw + (x / 2);
684 for (i=w; i>0; i--) {
686 // determine the bit shift for the DIB pixel
687 dib_shift = mod(w-i, 2);
688 if(dib_shift > 0) dib_shift = 4;
692 for (j=h; j>0; j--) {
693 *dibTmp = *bp << dib_shift | *(bp + 1);
698 if(dib_shift == 0) dib++;
703 void DIB_BltToDFB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw)
705 // This algorithm converts a DIB into a DFB
707 unsigned char *bp, *bpX, *dib, *dibTmp;
708 int i, j, dib_shift, dib_and;
711 dib = bdib + y * dibw + (x / 2);
713 for (i=w; i>0; i--) {
715 // determine the bit shift for the DIB pixel
716 dib_shift = mod(w-i, 2);
728 for (j=h; j>0; j--) {
729 *bp = (*dibTmp & dib_and) >> dib_shift;
735 if(dib_shift == 0) dib++;