X-Git-Url: http://git.jankratochvil.net/?p=reactos.git;a=blobdiff_plain;f=subsys%2Fwin32k%2Feng%2Fbitblt.c;fp=subsys%2Fwin32k%2Feng%2Fbitblt.c;h=53f8046d1cf8b0af410e15faad68108e1e20d6fb;hp=c582ebf678d675afee37e2ce0f2e7ee0fb2223ff;hb=7c0db166f81fbe8c8b913d7f26048e337d383605;hpb=e3ed2d773259cc445c7ff8181ebd934931365328 diff --git a/subsys/win32k/eng/bitblt.c b/subsys/win32k/eng/bitblt.c index c582ebf..53f8046 100644 --- a/subsys/win32k/eng/bitblt.c +++ b/subsys/win32k/eng/bitblt.c @@ -14,11 +14,17 @@ #include "brush.h" #include "clip.h" #include "objects.h" +#include "../dib/dib.h" +#include "misc.h" #include #include #include #include #include +#include + +#define NDEBUG +#include BOOL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2) { @@ -40,119 +46,166 @@ BOOL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2) return(FALSE); } +static BOOL STDCALL +BltMask(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask, + RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush, + POINTL* BrushPoint) +{ + LONG i, j, dx, dy, c8; + BYTE *tMask, *lMask; + static BYTE maskbit[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + + dx = DestRect->right - DestRect->left; + dy = DestRect->bottom - DestRect->top; + + if (Mask != NULL) + { + tMask = Mask->pvBits; + for (j = 0; j < dy; j++) + { + lMask = tMask; + c8 = 0; + for (i = 0; i < dx; i++) + { + if (0 != (*lMask & maskbit[c8])) + { + DestGDI->DIB_PutPixel(Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor); + } + c8++; + if (8 == c8) + { + lMask++; + c8=0; + } + } + tMask += Mask->lDelta; + } + return TRUE; + } + else + { + return FALSE; + } +} + +static BOOL STDCALL +BltPatCopy(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask, + RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush, + POINTL* BrushPoint) +{ + // These functions are assigned if we're working with a DIB + // The assigned functions depend on the bitsPerPixel of the DIB + LONG y; + ULONG LineWidth; + + LineWidth = DestRect->right - DestRect->left; + for (y = DestRect->top; y < DestRect->bottom; y++) + { + DestGDI->DIB_HLine(Dest, DestRect->left, DestRect->right, y, Brush->iSolidColor); + } + + return TRUE; +} + INT abs(INT nm); BOOL STDCALL -EngBitBlt(SURFOBJ *Dest, - SURFOBJ *Source, +EngBitBlt(SURFOBJ *DestObj, + SURFOBJ *SourceObj, SURFOBJ *Mask, CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, RECTL *DestRect, POINTL *SourcePoint, - POINTL *MaskRect, + POINTL *MaskOrigin, BRUSHOBJ *Brush, POINTL *BrushOrigin, ROP4 rop4) { - BOOLEAN ret; - BYTE clippingType; - RECTL rclTmp; - POINTL ptlTmp; - RECT_ENUM RectEnum; - BOOL EnumMore; - PSURFGDI DestGDI, SourceGDI; - HSURF hTemp; - PSURFOBJ TempSurf = NULL; - BOOLEAN canCopyBits; - POINTL TempPoint; - RECTL TempRect; - SIZEL TempSize; - - if(Source != NULL) SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source); - if(Dest != NULL) DestGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Dest); - - if (Source != NULL) + BOOLEAN ret; + BYTE clippingType; + RECTL rclTmp; + POINTL ptlTmp; + RECT_ENUM RectEnum; + BOOL EnumMore; + PSURFGDI OutputGDI, InputGDI; + POINTL InputPoint; + RECTL InputRect; + RECTL OutputRect; + POINTL Translate; + INTENG_ENTER_LEAVE EnterLeaveSource; + INTENG_ENTER_LEAVE EnterLeaveDest; + PSURFOBJ InputObj; + PSURFOBJ OutputObj; + + /* Check for degenerate case: if height or width of DestRect is 0 pixels there's + nothing to do */ + if (DestRect->right == DestRect->left || DestRect->bottom == DestRect->top) { - MouseSafetyOnDrawStart(Source, SourceGDI, SourcePoint->x, SourcePoint->y, - (SourcePoint->x + abs(DestRect->right - DestRect->left)), - (SourcePoint->y + abs(DestRect->bottom - DestRect->top))); + return TRUE; } - MouseSafetyOnDrawStart(Dest, DestGDI, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); - // If we don't have to do anything special, we can punt to DrvCopyBits - // if it exists - if( (Mask == NULL) && (MaskRect == NULL) && (Brush == NULL) && - (BrushOrigin == NULL) && (rop4 == 0) ) - { - canCopyBits = TRUE; - } else - canCopyBits = FALSE; - - // Check for CopyBits or BitBlt hooks if one is not a GDI managed bitmap, IF: - // * The destination bitmap is not managed by the GDI OR - if(Dest->iType != STYPE_BITMAP) - { - // Destination surface is device managed - if (DestGDI->BitBlt!=NULL) + if (NULL != SourcePoint) { - if (Source!=NULL) - { - // Get the source into a format compatible surface - TempPoint.x = 0; - TempPoint.y = 0; - TempRect.top = 0; - TempRect.left = 0; - TempRect.bottom = DestRect->bottom - DestRect->top; - TempRect.right = DestRect->right - DestRect->left; - TempSize.cx = TempRect.right; - TempSize.cy = TempRect.bottom; - - hTemp = EngCreateBitmap(TempSize, - DIB_GetDIBWidthBytes(DestRect->right - DestRect->left, BitsPerFormat(Dest->iBitmapFormat)), - Dest->iBitmapFormat, 0, NULL); - TempSurf = (PSURFOBJ)AccessUserObject((ULONG)hTemp); - - // FIXME: Skip creating a TempSurf if we have the same BPP and palette - EngBitBlt(TempSurf, Source, NULL, NULL, ColorTranslation, &TempRect, SourcePoint, NULL, NULL, NULL, 0); - } - - ret = DestGDI->BitBlt(Dest, TempSurf, Mask, ClipRegion, - NULL, DestRect, &TempPoint, - MaskRect, Brush, BrushOrigin, rop4); - - MouseSafetyOnDrawEnd(Source, SourceGDI); - MouseSafetyOnDrawEnd(Dest, DestGDI); - - return ret; + InputRect.left = SourcePoint->x; + InputRect.right = SourcePoint->x + (DestRect->right - DestRect->left); + InputRect.top = SourcePoint->y; + InputRect.bottom = SourcePoint->y + (DestRect->bottom - DestRect->top); + } + else + { + InputRect.left = 0; + InputRect.right = DestRect->right - DestRect->left; + InputRect.top = 0; + InputRect.bottom = DestRect->bottom - DestRect->top; } - } - /* The code currently assumes there will be a source bitmap. This is not true when, for example, using this function to - * paint a brush pattern on the destination. */ - if(!Source) - { - DbgPrint("EngBitBlt: A source is currently required, even though not all operations require one (FIXME)\n"); + if (! IntEngEnter(&EnterLeaveSource, SourceObj, &InputRect, TRUE, &Translate, &InputObj)) + { return FALSE; - } + } - // * The source bitmap is not managed by the GDI and we didn't already obtain it using EngCopyBits from the device - if(Source->iType != STYPE_BITMAP && SourceGDI->CopyBits == NULL) - { - if (SourceGDI->BitBlt!=NULL) + if (NULL != SourcePoint) + { + InputPoint.x = SourcePoint->x + Translate.x; + InputPoint.y = SourcePoint->y + Translate.y; + } + else + { + InputPoint.x = 0; + InputPoint.y = 0; + } + + if (NULL != InputObj) { - // Request the device driver to return the bitmap in a format compatible with the device - ret = SourceGDI->BitBlt(Dest, Source, Mask, ClipRegion, - NULL, DestRect, SourcePoint, - MaskRect, Brush, BrushOrigin, rop4); + InputGDI = (PSURFGDI) AccessInternalObjectFromUserObject(InputObj); + } - MouseSafetyOnDrawEnd(Source, SourceGDI); - MouseSafetyOnDrawEnd(Dest, DestGDI); + OutputRect = *DestRect; - return ret; + if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj)) + { + IntEngLeave(&EnterLeaveSource); + return FALSE; + } + + OutputRect.left = DestRect->left + Translate.x; + OutputRect.right = DestRect->right + Translate.x; + OutputRect.top = DestRect->top + Translate.y; + OutputRect.bottom = DestRect->bottom + Translate.y; - // Convert the surface from the driver into the required destination surface + + if (NULL != OutputObj) + { + OutputGDI = (PSURFGDI)AccessInternalObjectFromUserObject(OutputObj); } + + /* The code currently assumes there will be a source bitmap. This is not true when, for example, using this function to + * paint a brush pattern on the destination. */ + if (NULL == InputObj && 0xaacc != rop4 && PATCOPY != rop4) + { + DbgPrint("EngBitBlt: A source is currently required, even though not all operations require one (FIXME)\n"); + return FALSE; } // Determine clipping type @@ -163,27 +216,41 @@ EngBitBlt(SURFOBJ *Dest, clippingType = ClipRegion->iDComplexity; } + if (0xaacc == rop4) + { + ret = BltMask(OutputObj, OutputGDI, Mask, &OutputRect, MaskOrigin, Brush, BrushOrigin); + IntEngLeave(&EnterLeaveDest); + IntEngLeave(&EnterLeaveSource); + return ret; + } else if (PATCOPY == rop4) { + ret = BltPatCopy(OutputObj, OutputGDI, Mask, &OutputRect, MaskOrigin, Brush, BrushOrigin); + IntEngLeave(&EnterLeaveDest); + IntEngLeave(&EnterLeaveSource); + return ret; + } + + // We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE] switch(clippingType) { case DC_TRIVIAL: - CopyBitsCopy(Dest, Source, DestGDI, SourceGDI, DestRect, SourcePoint, Source->lDelta, ColorTranslation); + OutputGDI->DIB_BitBlt(OutputObj, InputObj, OutputGDI, InputGDI, &OutputRect, &InputPoint, ColorTranslation); - MouseSafetyOnDrawEnd(Source, SourceGDI); - MouseSafetyOnDrawEnd(Dest, DestGDI); + IntEngLeave(&EnterLeaveDest); + IntEngLeave(&EnterLeaveSource); return(TRUE); case DC_RECT: // Clip the blt to the clip rectangle - EngIntersectRect(&rclTmp, DestRect, &ClipRegion->rclBounds); + EngIntersectRect(&rclTmp, &OutputRect, &ClipRegion->rclBounds); - ptlTmp.x = SourcePoint->x + rclTmp.left - DestRect->left; - ptlTmp.y = SourcePoint->y + rclTmp.top - DestRect->top; + ptlTmp.x = InputPoint.x + rclTmp.left - OutputRect.left; + ptlTmp.y = InputPoint.y + rclTmp.top - OutputRect.top; - MouseSafetyOnDrawEnd(Source, SourceGDI); - MouseSafetyOnDrawEnd(Dest, DestGDI); + IntEngLeave(&EnterLeaveDest); + IntEngLeave(&EnterLeaveSource); return(TRUE); @@ -200,10 +267,10 @@ EngBitBlt(SURFOBJ *Dest, RECTL* prcl = &RectEnum.arcl[0]; do { - EngIntersectRect(prcl, prcl, DestRect); + EngIntersectRect(prcl, prcl, &OutputRect); - ptlTmp.x = SourcePoint->x + prcl->left - DestRect->left; - ptlTmp.y = SourcePoint->y + prcl->top - DestRect->top; + ptlTmp.x = InputPoint.x + prcl->left - OutputRect.left; + ptlTmp.y = InputPoint.y + prcl->top - OutputRect.top; prcl++; @@ -212,14 +279,65 @@ EngBitBlt(SURFOBJ *Dest, } while(EnumMore); - MouseSafetyOnDrawEnd(Source, SourceGDI); - MouseSafetyOnDrawEnd(Dest, DestGDI); + IntEngLeave(&EnterLeaveDest); + IntEngLeave(&EnterLeaveSource); return(TRUE); } - MouseSafetyOnDrawEnd(Source, SourceGDI); - MouseSafetyOnDrawEnd(Dest, DestGDI); + IntEngLeave(&EnterLeaveDest); + IntEngLeave(&EnterLeaveSource); return(FALSE); } + +BOOL STDCALL +IntEngBitBlt(SURFOBJ *DestObj, + SURFOBJ *SourceObj, + SURFOBJ *Mask, + CLIPOBJ *ClipRegion, + XLATEOBJ *ColorTranslation, + RECTL *DestRect, + POINTL *SourcePoint, + POINTL *MaskOrigin, + BRUSHOBJ *Brush, + POINTL *BrushOrigin, + ROP4 rop4) +{ + BOOLEAN ret; + SURFGDI *DestGDI; + SURFGDI *SourceGDI; + + if (NULL != SourceObj) + { + SourceGDI = (PSURFGDI) AccessInternalObjectFromUserObject(SourceObj); + MouseSafetyOnDrawStart(SourceObj, SourceGDI, SourcePoint->x, SourcePoint->y, + (SourcePoint->x + abs(DestRect->right - DestRect->left)), + (SourcePoint->y + abs(DestRect->bottom - DestRect->top))); + } + + /* No success yet */ + ret = FALSE; + DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj); + MouseSafetyOnDrawStart(DestObj, DestGDI, DestRect->left, DestRect->top, + DestRect->right, DestRect->bottom); + + /* Call the driver's DrvBitBlt if available */ + if (NULL != DestGDI->BitBlt) { + ret = DestGDI->BitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation, + DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, rop4); + } + + if (! ret) { + ret = EngBitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation, + DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, rop4); + } + + MouseSafetyOnDrawEnd(DestObj, DestGDI); + if (NULL != SourceObj) + { + MouseSafetyOnDrawEnd(SourceObj, SourceGDI); + } + + return ret; +}