2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI BitBlt Functions
5 * FILE: subsys/win32k/eng/bitblt.c
6 * PROGRAMER: Jason Filby
11 #include <ddk/winddi.h>
12 #include <ddk/ntddk.h>
13 #include <ntos/minmax.h>
18 BOOL
EngIntersectRect(PRECTL prcDst
, PRECTL prcSrc1
, PRECTL prcSrc2
)
20 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
22 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
23 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
25 if (prcDst
->left
< prcDst
->right
)
27 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
28 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
30 if (prcDst
->top
< prcDst
->bottom
) return(TRUE
);
39 BOOL
EngBitBlt(SURFOBJ
*Dest
, SURFOBJ
*Source
,
40 SURFOBJ
*Mask
, CLIPOBJ
*ClipRegion
,
41 XLATEOBJ
*ColorTranslation
, RECTL
*DestRect
,
42 POINTL
*SourcePoint
, POINTL
*MaskRect
,
43 BRUSHOBJ
*Brush
, POINTL
*BrushOrigin
, ROP4 rop4
)
50 PSURFGDI DestGDI
, SourceGDI
;
58 SourceGDI
= AccessInternalObjectFromUserObject(Source
);
60 // If we don't have to do anything special, we can punt to DrvCopyBits
62 if( (Mask
== NULL
) && (MaskRect
== NULL
) && (Brush
== NULL
) &&
63 (BrushOrigin
== NULL
) && (rop4
== 0) )
69 // Check for CopyBits or BitBlt hooks if one is not a GDI managed bitmap, IF:
70 // * The destination bitmap is not managed by the GDI OR
71 if(Dest
->iType
!= STYPE_BITMAP
)
73 // Destination surface is device managed
74 DestGDI
= AccessInternalObjectFromUserObject(Dest
);
76 if (DestGDI
->BitBlt
!=NULL
)
78 // The destination is device managed, therefore get the source into a format compatible surface
83 TempRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
84 TempRect
.right
= DestRect
->right
- DestRect
->left
;
85 TempSize
.cx
= TempRect
.right
;
86 TempSize
.cy
= TempRect
.bottom
;
88 hTemp
= EngCreateBitmap(TempSize
,
89 DIB_GetDIBWidthBytes(DestRect
->right
- DestRect
->left
, BitsPerFormat(Dest
->iBitmapFormat
)),
90 Dest
->iBitmapFormat
, 0, NULL
);
91 TempSurf
= AccessUserObject(hTemp
);
93 // FIXME: Skip creating a TempSurf if we have the same BPP and palette
94 EngBitBlt(TempSurf
, Source
, NULL
, NULL
, ColorTranslation
, &TempRect
, SourcePoint
, NULL
, NULL
, NULL
, 0);
96 return DestGDI
->BitBlt(Dest
, TempSurf
, Mask
, ClipRegion
,
97 NULL
, DestRect
, &TempPoint
,
98 MaskRect
, Brush
, BrushOrigin
, rop4
);
102 // * The source bitmap is not managed by the GDI and we didn't already obtain it using EngCopyBits from the device
103 if(Source
->iType
!= STYPE_BITMAP
&& SourceGDI
->CopyBits
== NULL
)
105 if (SourceGDI
->BitBlt
!=NULL
)
107 // Request the device driver to return the bitmap in a format compatible with the device
108 return SourceGDI
->BitBlt(Dest
, Source
, Mask
, ClipRegion
,
109 NULL
, DestRect
, SourcePoint
,
110 MaskRect
, Brush
, BrushOrigin
, rop4
);
112 // Convert the surface from the driver into the required destination surface
116 DestGDI
= AccessInternalObjectFromUserObject(Dest
);
117 SourceGDI
= AccessInternalObjectFromUserObject(Source
);
119 // Determine clipping type
120 if (ClipRegion
== (CLIPOBJ
*) NULL
)
122 clippingType
= DC_TRIVIAL
;
124 clippingType
= ClipRegion
->iDComplexity
;
127 // We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE]
131 CopyBitsCopy(Dest
, Source
, DestGDI
, SourceGDI
, DestRect
, SourcePoint
, Source
->lDelta
, ColorTranslation
);
136 // Clip the blt to the clip rectangle
137 EngIntersectRect(&rclTmp
, DestRect
, &ClipRegion
->rclBounds
);
139 ptlTmp
.x
= SourcePoint
->x
+ rclTmp
.left
- DestRect
->left
;
140 ptlTmp
.y
= SourcePoint
->y
+ rclTmp
.top
- DestRect
->top
;
146 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, ENUM_RECT_LIMIT
);
149 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
153 RECTL
* prclEnd
= &RectEnum
.arcl
[RectEnum
.c
];
154 RECTL
* prcl
= &RectEnum
.arcl
[0];
157 EngIntersectRect(prcl
, prcl
, DestRect
);
159 ptlTmp
.x
= SourcePoint
->x
+ prcl
->left
- DestRect
->left
;
160 ptlTmp
.y
= SourcePoint
->y
+ prcl
->top
- DestRect
->top
;
164 } while (prcl
< prclEnd
);