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>
17 #include "../dib/dib.h"
18 #include <include/mouse.h>
19 #include <include/object.h>
20 #include <include/dib.h>
21 #include <include/surface.h>
22 #include <include/copybits.h>
25 #include <win32k/debug1.h>
27 BOOL
EngIntersectRect(PRECTL prcDst
, PRECTL prcSrc1
, PRECTL prcSrc2
)
29 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
31 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
32 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
34 if (prcDst
->left
< prcDst
->right
)
36 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
37 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
39 if (prcDst
->top
< prcDst
->bottom
) return(TRUE
);
48 BltMask(SURFOBJ
*Dest
, PSURFGDI DestGDI
, SURFOBJ
*Mask
,
49 RECTL
*DestRect
, POINTL
*MaskPoint
, BRUSHOBJ
* Brush
,
52 LONG i
, j
, dx
, dy
, c8
;
54 PFN_DIB_PutPixel DIB_PutPixel
;
55 static BYTE maskbit
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
57 // Assign DIB functions according to bytes per pixel
58 switch(BitsPerFormat(Dest
->iBitmapFormat
))
61 DIB_PutPixel
= (PFN_DIB_PutPixel
)DIB_1BPP_PutPixel
;
65 DIB_PutPixel
= (PFN_DIB_PutPixel
)DIB_4BPP_PutPixel
;
69 DIB_PutPixel
= (PFN_DIB_PutPixel
)DIB_16BPP_PutPixel
;
73 DIB_PutPixel
= (PFN_DIB_PutPixel
)DIB_24BPP_PutPixel
;
77 DbgPrint("BltMask: unsupported DIB format %u (bitsPerPixel:%u)\n", Dest
->iBitmapFormat
,
78 BitsPerFormat(Dest
->iBitmapFormat
));
82 dx
= DestRect
->right
- DestRect
->left
;
83 dy
= DestRect
->bottom
- DestRect
->top
;
88 for (j
= 0; j
< dy
; j
++)
92 for (i
= 0; i
< dx
; i
++)
94 if (0 != (*lMask
& maskbit
[c8
]))
96 DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
105 tMask
+= Mask
->lDelta
;
116 BltPatCopy(SURFOBJ
*Dest
, PSURFGDI DestGDI
, SURFOBJ
*Mask
,
117 RECTL
*DestRect
, POINTL
*MaskPoint
, BRUSHOBJ
* Brush
,
120 // These functions are assigned if we're working with a DIB
121 // The assigned functions depend on the bitsPerPixel of the DIB
122 PFN_DIB_HLine DIB_HLine
;
126 MouseSafetyOnDrawStart(Dest
, DestGDI
, DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
127 // Assign DIB functions according to bytes per pixel
128 DPRINT("BPF: %d\n", BitsPerFormat(Dest
->iBitmapFormat
));
129 switch(BitsPerFormat(Dest
->iBitmapFormat
))
132 DIB_HLine
= (PFN_DIB_HLine
)DIB_4BPP_HLine
;
136 DIB_HLine
= (PFN_DIB_HLine
)DIB_16BPP_HLine
;
140 DIB_HLine
= (PFN_DIB_HLine
)DIB_24BPP_HLine
;
144 DbgPrint("BltPatCopy: unsupported DIB format %u (bitsPerPixel:%u)\n", Dest
->iBitmapFormat
,
145 BitsPerFormat(Dest
->iBitmapFormat
));
147 MouseSafetyOnDrawEnd(Dest
, DestGDI
);
151 LineWidth
= DestRect
->right
- DestRect
->left
;
152 for (y
= DestRect
->top
; y
< DestRect
->bottom
; y
++)
154 DIB_HLine(Dest
, DestRect
->left
, DestRect
->right
, y
, Brush
->iSolidColor
);
156 MouseSafetyOnDrawEnd(Dest
, DestGDI
);
164 EngBitBlt(SURFOBJ
*Dest
,
168 XLATEOBJ
*ColorTranslation
,
182 PSURFGDI DestGDI
, SourceGDI
;
184 PSURFOBJ TempSurf
= NULL
;
190 if(Source
!= NULL
) SourceGDI
= (PSURFGDI
)AccessInternalObjectFromUserObject(Source
);
191 if(Dest
!= NULL
) DestGDI
= (PSURFGDI
)AccessInternalObjectFromUserObject(Dest
);
195 MouseSafetyOnDrawStart(Source
, SourceGDI
, SourcePoint
->x
, SourcePoint
->y
,
196 (SourcePoint
->x
+ abs(DestRect
->right
- DestRect
->left
)),
197 (SourcePoint
->y
+ abs(DestRect
->bottom
- DestRect
->top
)));
199 MouseSafetyOnDrawStart(Dest
, DestGDI
, DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
201 // If we don't have to do anything special, we can punt to DrvCopyBits
203 if( (Mask
== NULL
) && (MaskOrigin
== NULL
) && (Brush
== NULL
) &&
204 (BrushOrigin
== NULL
) && (rop4
== 0) )
210 // Check for CopyBits or BitBlt hooks if one is not a GDI managed bitmap, IF:
211 // * The destination bitmap is not managed by the GDI OR
212 if(Dest
->iType
!= STYPE_BITMAP
)
214 // Destination surface is device managed
215 if (DestGDI
->BitBlt
!=NULL
)
219 // Get the source into a format compatible surface
224 TempRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
225 TempRect
.right
= DestRect
->right
- DestRect
->left
;
226 TempSize
.cx
= TempRect
.right
;
227 TempSize
.cy
= TempRect
.bottom
;
229 hTemp
= EngCreateBitmap(TempSize
,
230 DIB_GetDIBWidthBytes(DestRect
->right
- DestRect
->left
, BitsPerFormat(Dest
->iBitmapFormat
)),
231 Dest
->iBitmapFormat
, 0, NULL
);
232 TempSurf
= (PSURFOBJ
)AccessUserObject((ULONG
)hTemp
);
234 // FIXME: Skip creating a TempSurf if we have the same BPP and palette
235 EngBitBlt(TempSurf
, Source
, NULL
, NULL
, ColorTranslation
, &TempRect
, SourcePoint
, NULL
, NULL
, NULL
, 0);
238 ret
= DestGDI
->BitBlt(Dest
, TempSurf
, Mask
, ClipRegion
,
239 NULL
, DestRect
, &TempPoint
,
240 MaskOrigin
, Brush
, BrushOrigin
, rop4
);
242 MouseSafetyOnDrawEnd(Source
, SourceGDI
);
243 MouseSafetyOnDrawEnd(Dest
, DestGDI
);
249 /* The code currently assumes there will be a source bitmap. This is not true when, for example, using this function to
250 * paint a brush pattern on the destination. */
251 if(!Source
&& 0xaacc != rop4
&& PATCOPY
!= rop4
)
253 DbgPrint("EngBitBlt: A source is currently required, even though not all operations require one (FIXME)\n");
257 // * The source bitmap is not managed by the GDI and we didn't already obtain it using EngCopyBits from the device
258 if(NULL
!= Source
&& STYPE_BITMAP
!= Source
->iType
&& NULL
== SourceGDI
->CopyBits
)
260 if (SourceGDI
->BitBlt
!=NULL
)
262 // Request the device driver to return the bitmap in a format compatible with the device
263 ret
= SourceGDI
->BitBlt(Dest
, Source
, Mask
, ClipRegion
,
264 NULL
, DestRect
, SourcePoint
,
265 MaskOrigin
, Brush
, BrushOrigin
, rop4
);
267 MouseSafetyOnDrawEnd(Source
, SourceGDI
);
268 MouseSafetyOnDrawEnd(Dest
, DestGDI
);
272 // Convert the surface from the driver into the required destination surface
276 // Determine clipping type
277 if (ClipRegion
== (CLIPOBJ
*) NULL
)
279 clippingType
= DC_TRIVIAL
;
281 clippingType
= ClipRegion
->iDComplexity
;
286 return BltMask(Dest
, DestGDI
, Mask
, DestRect
, MaskOrigin
, Brush
, BrushOrigin
);
287 } else if (PATCOPY
== rop4
) {
288 return BltPatCopy(Dest
, DestGDI
, Mask
, DestRect
, MaskOrigin
, Brush
, BrushOrigin
);
292 // We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE]
296 CopyBitsCopy(Dest
, Source
, DestGDI
, SourceGDI
, DestRect
, SourcePoint
, Source
->lDelta
, ColorTranslation
);
298 MouseSafetyOnDrawEnd(Source
, SourceGDI
);
299 MouseSafetyOnDrawEnd(Dest
, DestGDI
);
305 // Clip the blt to the clip rectangle
306 EngIntersectRect(&rclTmp
, DestRect
, &ClipRegion
->rclBounds
);
308 ptlTmp
.x
= SourcePoint
->x
+ rclTmp
.left
- DestRect
->left
;
309 ptlTmp
.y
= SourcePoint
->y
+ rclTmp
.top
- DestRect
->top
;
311 MouseSafetyOnDrawEnd(Source
, SourceGDI
);
312 MouseSafetyOnDrawEnd(Dest
, DestGDI
);
318 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, ENUM_RECT_LIMIT
);
321 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
325 RECTL
* prclEnd
= &RectEnum
.arcl
[RectEnum
.c
];
326 RECTL
* prcl
= &RectEnum
.arcl
[0];
329 EngIntersectRect(prcl
, prcl
, DestRect
);
331 ptlTmp
.x
= SourcePoint
->x
+ prcl
->left
- DestRect
->left
;
332 ptlTmp
.y
= SourcePoint
->y
+ prcl
->top
- DestRect
->top
;
336 } while (prcl
< prclEnd
);
341 MouseSafetyOnDrawEnd(Source
, SourceGDI
);
342 MouseSafetyOnDrawEnd(Dest
, DestGDI
);
347 MouseSafetyOnDrawEnd(Source
, SourceGDI
);
348 MouseSafetyOnDrawEnd(Dest
, DestGDI
);