#include "brush.h"
#include "bitblt.h"
-// FIXME:
-// RGBtoULONG (eng/xlate.c) will be faster than RtlCopyMemory?
+typedef BOOL (*PFN_VGABlt)(SURFOBJ*, SURFOBJ*, XLATEOBJ*, RECTL*, POINTL*);
-// Note: All of our BitBlt ops expect to be working with 4BPP data
-
-typedef BOOL (*PFN_VGABlt)(SURFOBJ *, SURFOBJ *, SURFOBJ *, XLATEOBJ *,
- RECTL *, POINTL *, POINTL *,
- BRUSHOBJ *, POINTL *, ROP4);
-
-BOOL DIBtoVGA(
- SURFOBJ *Dest, SURFOBJ *Source, SURFOBJ *Mask, XLATEOBJ *ColorTranslation,
- RECTL *DestRect, POINTL *SourcePoint, POINTL *MaskPoint,
- BRUSHOBJ *Brush, POINTL *BrushPoint, ROP4 rop4)
+BOOL
+DIBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
+ RECTL *DestRect, POINTL *SourcePoint)
{
LONG i, j, dx, dy, alterx, altery, idxColor, RGBulong = 0, c8;
BYTE *GDIpos, *initial, *tMask, *lMask;
- if(Source != NULL) {
- GDIpos = Source->pvBits /* +
- SourcePoint->y * Source->lDelta + (SourcePoint->x >> 1) */ ;
- }
-
+ GDIpos = Source->pvBits;
+
dx = DestRect->right - DestRect->left;
dy = DestRect->bottom - DestRect->top;
-
+
alterx = abs(SourcePoint->x - DestRect->left);
altery = abs(SourcePoint->y - DestRect->top);
- // FIXME: ColorTranslation will never be null. We must always map the colors (see PCGPE's bmp.txt)
-
- if(ColorTranslation == NULL)
- {
-
- if(Mask != NULL)
- {
- if(rop4 == 0xAACC) { // no source, just paint the brush according to the mask
-
- tMask = Mask->pvBits;
- for (j=0; j<dy; j++)
- {
- lMask = tMask;
- c8 = 0;
- for (i=0; i<dx; i++)
- {
- if((*lMask & maskbit[c8]) != 0)
- vgaPutPixel(DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
- c8++;
- if(c8 == 8) { lMask++; c8=0; }
- }
- tMask += Mask->lDelta;
- }
- }
- } else if (rop4 == PATCOPY)
- {
- for (j=0;j<dy;j++)
- {
- for (i=0;i<dx;i++)
- {
- vgaPutPixel(DestRect->left+i, DestRect->top+j,
- Brush->iSolidColor);
- }
- }
- }
- else
- DIB_BltToVGA(DestRect->left, DestRect->top, dx, dy, Source->pvBits, Source->lDelta);
-
- } else {
-
- // Perform color translation
- for(j=SourcePoint->y; j<SourcePoint->y+dy; j++)
+ if (ColorTranslation == NULL)
+ {
+ DIB_BltToVGA(DestRect->left, DestRect->top, dx, dy, Source->pvBits,
+ Source->lDelta);
+ }
+ else
{
- initial = GDIpos;
-
- for(i=SourcePoint->x; i<SourcePoint->x+dx; i++)
- {
- idxColor = XLATEOBJ_iXlate(ColorTranslation, *GDIpos);
- vgaPutPixel(i+alterx, j+altery, idxColor);
- GDIpos+=1;
- }
- GDIpos = initial + Source->lDelta;
+ /* Perform color translation */
+ for (j = SourcePoint->y; j < SourcePoint->y+dy; j++)
+ {
+ initial = GDIpos;
+
+ for (i=SourcePoint->x; i<SourcePoint->x+dx; i++)
+ {
+ idxColor = XLATEOBJ_iXlate(ColorTranslation, *GDIpos);
+ vgaPutPixel(i+alterx, j+altery, idxColor);
+ GDIpos+=1;
+ }
+ GDIpos = initial + Source->lDelta;
+ }
}
- }
}
-BOOL VGAtoDIB(
- SURFOBJ *Dest, SURFOBJ *Source, SURFOBJ *Mask, XLATEOBJ *ColorTranslation,
- RECTL *DestRect, POINTL *SourcePoint, POINTL *MaskPoint,
- BRUSHOBJ *Brush, POINTL *BrushPoint, ROP4 rop4)
+BOOL
+VGAtoDIB(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
+ RECTL *DestRect, POINTL *SourcePoint)
{
LONG i, j, dx, dy, RGBulong;
BYTE *GDIpos, *initial, idxColor;
-
+
// Used by the temporary DFB
PDEVSURF TargetSurf;
DEVSURF DestDevSurf;
}
}
-BOOL DFBtoVGA(
- SURFOBJ *Dest, SURFOBJ *Source, SURFOBJ *Mask, XLATEOBJ *ColorTranslation,
- RECTL *DestRect, POINTL *SourcePoint, POINTL *MaskPoint,
- BRUSHOBJ *Brush, POINTL *BrushPoint, ROP4 rop4)
+BOOL
+DFBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
+ RECTL *DestRect, POINTL *SourcePoint)
{
// Do DFBs need color translation??
}
-BOOL VGAtoDFB(
- SURFOBJ *Dest, SURFOBJ *Source, SURFOBJ *Mask, XLATEOBJ *ColorTranslation,
- RECTL *DestRect, POINTL *SourcePoint, POINTL *MaskPoint,
- BRUSHOBJ *Brush, POINTL *BrushPoint, ROP4 rop4)
+BOOL
+VGAtoDFB(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
+ RECTL *DestRect, POINTL *SourcePoint)
{
// Do DFBs need color translation??
}
-BOOL VGAtoVGA(
- SURFOBJ *Dest, SURFOBJ *Source, SURFOBJ *Mask, XLATEOBJ *ColorTranslation,
- RECTL *DestRect, POINTL *SourcePoint, POINTL *MaskPoint,
- BRUSHOBJ *Brush, POINTL *BrushPoint, ROP4 rop4)
+BOOL
+VGAtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
+ RECTL *DestRect, POINTL *SourcePoint)
{
// FIXME: Use fast blts instead of get and putpixels
return TRUE;
}
-
BOOL STDCALL
-DrvBitBlt(SURFOBJ *Dest,
- SURFOBJ *Source,
- SURFOBJ *Mask,
- CLIPOBJ *Clip,
- XLATEOBJ *ColorTranslation,
- RECTL *DestRect,
- POINTL *SourcePoint,
- POINTL *MaskPoint,
- BRUSHOBJ *Brush,
- POINTL *BrushPoint,
- ROP4 rop4)
+VGADDI_BltBrush(SURFOBJ* Dest, XLATEOBJ* ColorTranslation, RECTL* DestRect,
+ BRUSHOBJ* Brush, POINTL* BrushPoint, ROP4 Rop4)
{
- RECT_ENUM RectEnum;
- BOOL EnumMore;
- PFN_VGABlt BltOperation;
- ULONG SourceType;
+ UCHAR SolidColor;
+ ULONG Left;
+ ULONG Right;
+ ULONG Length;
+ PUCHAR Video;
+ UCHAR Mask;
+ ULONG i, j;
+
+ /* Punt brush blts to non-device surfaces. */
+ if (Dest->iType != STYPE_DEVICE)
+ {
+ return(FALSE);
+ }
- if(Source == NULL)
- {
- SourceType = STYPE_BITMAP;
- } else
- SourceType = Source->iType;
+ /* Punt pattern fills. */
+ if (Rop4 == PATCOPY && Brush->iSolidColor == 0xFFFFFFFF)
+ {
+ return(FALSE);
+ }
+ if (Rop4 == PATCOPY)
+ {
+ SolidColor = Brush->iSolidColor;
+ }
+ else if (Rop4 == WHITENESS)
+ {
+ SolidColor = 1;
+ }
+ else
+ {
+ SolidColor = 0;
+ }
-DPRINT("VGADDIBitBlt: Dest->pvScan0: %08x\n", Dest->pvScan0);
+ /* Fill any pixels on the left which don't fall into a full row of eight. */
+ if ((DestRect->left % 8) != 0)
+ {
+ /* Disable writes to pixels outside of the destination rectangle. */
+ Mask = (1 << (8 - (DestRect->left % 8))) - 1;
+ if ((DestRect->right - DestRect->left) < (8 - (DestRect->left % 8)))
+ {
+ Mask &= ~((1 << (8 - (DestRect->right % 8))) - 1);
+ }
+ WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
+ WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask);
+
+ /* Write the same color to each pixel. */
+ Video = (PUCHAR)vidmem + DestRect->top * 80 + (DestRect->left >> 3);
+ for (i = DestRect->top; i < DestRect->bottom; i++, Video+=80)
+ {
+ (VOID)READ_REGISTER_UCHAR(Video);
+ WRITE_REGISTER_UCHAR(Video, SolidColor);
+ }
+ }
- // Determine the bltbit operation
+ /* Enable writes to all pixels. */
+ WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
+ WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF);
+
+ /* Have we finished. */
+ if ((DestRect->right - DestRect->left) < (8 - (DestRect->left % 8)))
+ {
+ return(TRUE);
+ }
+
+ /* Fill any whole rows of eight pixels. */
+ Left = (DestRect->left + 7) & ~0x7;
+ Length = (DestRect->right >> 3) - (Left >> 3);
+ for (i = DestRect->top; i < DestRect->bottom; i++)
+ {
+ Video = (PUCHAR)vidmem + i * 80 + (Left >> 3);
+ for (j = 0; j < Length; j++, Video++)
+ {
+ WRITE_REGISTER_UCHAR(Video, SolidColor);
+ }
+ }
- if((SourceType == STYPE_BITMAP) && (Dest->iType == STYPE_DEVICE))
- {
-DPRINT("DIB2VGA\n");
+ /* Fill any pixels on the right which don't fall into a complete row. */
+ if ((DestRect->right % 8) != 0)
+ {
+ /* Disable writes to pixels outside the destination rectangle. */
+ Mask = ~((1 << (8 - (DestRect->right % 8))) - 1);
+ WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
+ WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask);
+
+ Video = (PUCHAR)vidmem + DestRect->top * 80 + (DestRect->right >> 3);
+ for (i = DestRect->top; i < DestRect->bottom; i++, Video+=80)
+ {
+ /* Read the existing colours for this pixel into the latches. */
+ (VOID)READ_REGISTER_UCHAR(Video);
+ /* Write the new colour for the pixels selected in the mask. */
+ WRITE_REGISTER_UCHAR(Video, SolidColor);
+ }
+
+ /* Restore the default write masks. */
+ WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
+ WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF);
+ }
+ return(TRUE);
+}
+
+BOOL STDCALL
+VGADDI_BltSrc(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
+ RECTL *DestRect, POINTL *SourcePoint)
+{
+ RECT_ENUM RectEnum;
+ BOOL EnumMore;
+ PFN_VGABlt BltOperation;
+ ULONG SourceType;
+
+ SourceType = Source->iType;
+
+ if (SourceType == STYPE_BITMAP && Dest->iType == STYPE_DEVICE)
+ {
BltOperation = DIBtoVGA;
- } else
- if((SourceType == STYPE_DEVICE) && (Dest->iType == STYPE_BITMAP))
- {
-DPRINT("VGA2DIB\n");
+ }
+ else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_BITMAP)
+ {
BltOperation = VGAtoDIB;
- } else
- if((SourceType == STYPE_DEVICE) && (Dest->iType == STYPE_DEVICE))
- {
-DPRINT("VGA2VGA\n");
+ }
+ else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_DEVICE)
+ {
BltOperation = VGAtoVGA;
- } else
- if((SourceType == STYPE_DEVBITMAP) && (Dest->iType == STYPE_DEVICE))
- {
-DPRINT("DFB2VGA\n");
+ }
+ else if (SourceType == STYPE_DEVBITMAP && Dest->iType == STYPE_DEVICE)
+ {
BltOperation = DFBtoVGA;
- } else
- if((SourceType == STYPE_DEVICE) && (Dest->iType == STYPE_DEVBITMAP))
- {
-DPRINT("VGA2DFB\n");
+ }
+ else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_DEVBITMAP)
+ {
BltOperation = VGAtoDFB;
- } else
- {
-DPRINT("VGA:bitblt.c: Can't handle requested BitBlt operation (source:%u dest:%u)\n", SourceType, Dest->iType);
- // Cannot handle given surfaces for VGA BitBlt
- return FALSE;
+ }
+ else
+ {
+ /* Punt blts not involving a device or a device-bitmap. */
+ return(FALSE);
}
- // Perform the necessary operatings according to the clipping
-
- if(Clip == NULL)
- {
- BltOperation(Dest, Source, Mask, ColorTranslation, DestRect,
- SourcePoint, MaskPoint, Brush, BrushPoint, rop4);
- } else
- {
- switch(Clip->iMode) {
-
- case TC_RECTANGLES:
-
- if (Clip->iDComplexity == DC_RECT)
- {
- // FIXME: Intersect clip rectangle
-
- BltOperation(Dest, Source, Mask, ColorTranslation,
- DestRect, SourcePoint, MaskPoint, Brush, BrushPoint, rop4);
- } else {
-
- // Enumerate all the rectangles and draw them
-
- /* CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY,
- ENUM_RECT_LIMIT);
-
- do {
- EnumMore = CLIPOBJ_bEnum(Clip, sizeof(RectEnum), (PVOID) &RectEnum);
- // FIXME: Calc new source point (diff between new & old destrects?)
-
- VGADDIFillSolid(Dest, Srouce, Mask,
- &RectEnum.arcl[0], NewSourcePoint);
+ BltOperation(Dest, Source, ColorTranslation, DestRect, SourcePoint);
+ return(TRUE);
+}
- } while (EnumMore); */
- }
- }
- }
+BOOL STDCALL
+VGADDI_BltMask(SURFOBJ *Dest, SURFOBJ *Mask, XLATEOBJ *ColorTranslation,
+ RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush,
+ POINTL* BrushPoint)
+{
+ LONG i, j, dx, dy, idxColor, RGBulong = 0, c8;
+ BYTE *initial, *tMask, *lMask;
+
+ dx = DestRect->right - DestRect->left;
+ dy = DestRect->bottom - DestRect->top;
+
+ if (ColorTranslation == NULL)
+ {
+ if (Mask != NULL)
+ {
+ tMask = Mask->pvBits;
+ for (j=0; j<dy; j++)
+ {
+ lMask = tMask;
+ c8 = 0;
+ for (i=0; i<dx; i++)
+ {
+ if((*lMask & maskbit[c8]) != 0)
+ {
+ vgaPutPixel(DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
+ }
+ c8++;
+ if(c8 == 8) { lMask++; c8=0; }
+ }
+ tMask += Mask->lDelta;
+ }
+ }
+ }
+}
- return TRUE;
+BOOL STDCALL
+DrvBitBlt(SURFOBJ *Dest,
+ SURFOBJ *Source,
+ SURFOBJ *Mask,
+ CLIPOBJ *Clip,
+ XLATEOBJ *ColorTranslation,
+ RECTL *DestRect,
+ POINTL *SourcePoint,
+ POINTL *MaskPoint,
+ BRUSHOBJ *Brush,
+ POINTL *BrushPoint,
+ ROP4 rop4)
+{
+ /* Punt bitblts with complex clipping to the GDI. */
+ if (Clip != NULL)
+ {
+ return(FALSE);
+ }
+
+ switch (rop4)
+ {
+ case BLACKNESS:
+ case PATCOPY:
+ case WHITENESS:
+ return(VGADDI_BltBrush(Dest, ColorTranslation, DestRect, Brush,
+ BrushPoint, rop4));
+
+ case SRCCOPY:
+ return(VGADDI_BltSrc(Dest, Source, ColorTranslation, DestRect,
+ SourcePoint));
+
+ case 0xAACC:
+ return(VGADDI_BltMask(Dest, Mask, ColorTranslation, DestRect,
+ MaskPoint, Brush, BrushPoint));
+
+ default:
+ return(FALSE);
+ }
}