2 * PROJECT: ReactOS VGA display driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/video/displays/vga/objects/bitblt.c
13 typedef BOOL (*PFN_VGABlt
)(SURFOBJ
*, SURFOBJ
*, XLATEOBJ
*, RECTL
*, POINTL
*);
14 typedef BOOL (APIENTRY
*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
17 XLATEOBJ
* ColorTranslation
,
25 static BOOL FASTCALL
VGADDI_IntersectRect(
30 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
32 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
33 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
35 if (prcDst
->left
< prcDst
->right
)
37 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
38 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
40 if (prcDst
->top
< prcDst
->bottom
) return(TRUE
);
48 void DIB_BltToVGA_Fixed(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, int mod
);
54 IN XLATEOBJ
*ColorTranslation
,
56 IN POINTL
*SourcePoint
)
60 dx
= DestRect
->right
- DestRect
->left
;
61 dy
= DestRect
->bottom
- DestRect
->top
;
63 if (NULL
== ColorTranslation
|| 0 != (ColorTranslation
->flXlate
& XO_TRIVIAL
))
65 DIB_BltToVGA(DestRect
->left
, DestRect
->top
, dx
, dy
,
66 (PVOID
)((ULONG_PTR
)Source
->pvScan0
+ SourcePoint
->y
* Source
->lDelta
+ (SourcePoint
->x
>> 1)),
67 Source
->lDelta
, SourcePoint
->x
% 2);
71 /* Perform color translation */
72 DIB_BltToVGAWithXlate(DestRect
->left
, DestRect
->top
, dx
, dy
,
73 (PVOID
)((ULONG_PTR
)Source
->pvScan0
+ SourcePoint
->y
* Source
->lDelta
+ (SourcePoint
->x
>> 1)),
74 Source
->lDelta
, ColorTranslation
);
83 IN XLATEOBJ
*ColorTranslation
,
85 IN POINTL
*SourcePoint
)
88 UCHAR
*GDIpos
, *initial
;
90 /* Used by the temporary DFB */
91 //DEVSURF DestDevSurf;
93 /* FIXME: Optimize to retrieve entire bytes at a time (see ../vgavideo/vgavideo.c:vgaGetByte) */
95 GDIpos
= Dest
->pvScan0
/* + (DestRect->top * Dest->lDelta) + (DestRect->left >> 1) */ ;
96 dx
= DestRect
->right
- DestRect
->left
;
97 dy
= DestRect
->bottom
- DestRect
->top
;
99 if (ColorTranslation
== NULL
)
101 /* Prepare a Dest Dev Target and copy from the DFB to the DIB */
102 //DestDevSurf.NextScan = Dest->lDelta;
103 //DestDevSurf.StartBmp = Dest->pvScan0;
105 DIB_BltFromVGA(SourcePoint
->x
, SourcePoint
->y
, dx
, dy
, Dest
->pvScan0
, Dest
->lDelta
);
109 /* Color translation */
110 for (j
= SourcePoint
->y
; j
< SourcePoint
->y
+ dy
; j
++)
113 for (i
= SourcePoint
->x
; i
< SourcePoint
->x
+ dx
; i
++)
115 *GDIpos
= XLATEOBJ_iXlate(ColorTranslation
, vgaGetPixel(i
, j
));
118 GDIpos
= initial
+ Dest
->lDelta
;
128 IN XLATEOBJ
*ColorTranslation
,
130 IN POINTL
*SourcePoint
)
132 /* Do DFBs need color translation?? */
140 IN XLATEOBJ
*ColorTranslation
,
142 IN POINTL
*SourcePoint
)
144 /* Do DFBs need color translation?? */
152 IN XLATEOBJ
*ColorTranslation
,
154 IN POINTL
*SourcePoint
)
156 LONG i
, i2
, j
, dx
, dy
, alterx
, altery
;
157 static char buf
[SCREEN_X
];
159 /* Calculate deltas */
160 dx
= DestRect
->right
- DestRect
->left
;
161 dy
= DestRect
->bottom
- DestRect
->top
;
163 alterx
= DestRect
->left
- SourcePoint
->x
;
164 altery
= DestRect
->top
- SourcePoint
->y
;
169 if (SourcePoint
->y
>= DestRect
->top
)
171 for (j
= SourcePoint
->y
; j
< SourcePoint
->y
+ dy
; j
++)
173 LONG j2
= j
+ altery
;
174 vgaReadScan ( i
, j
, dx
, buf
);
175 vgaWriteScan ( i2
, j2
, dx
, buf
);
180 for(j
= (SourcePoint
->y
+ dy
- 1); j
>= SourcePoint
->y
; j
--)
182 LONG j2
= j
+ altery
;
183 vgaReadScan ( i
, j
, dx
, buf
);
184 vgaWriteScan ( i2
, j2
, dx
, buf
);
195 IN SURFOBJ
* MaskSurf
,
196 IN XLATEOBJ
* ColorTranslation
,
198 IN POINTL
* SourcePoint
,
199 IN POINTL
* MaskPoint
,
201 IN POINTL
* BrushPoint
,
204 UCHAR SolidColor
= 0;
210 ULONG RasterOp
= VGA_NORMAL
;
212 /* Punt brush blts to non-device surfaces. */
213 if (Dest
->iType
!= STYPE_DEVICE
)
216 /* Punt pattern fills. */
217 if ((GET_OPINDEX_FROM_ROP4(Rop4
) == GET_OPINDEX_FROM_ROP3(PATCOPY
)
218 || GET_OPINDEX_FROM_ROP4(Rop4
) == GET_OPINDEX_FROM_ROP3(PATINVERT
)) &&
219 Brush
->iSolidColor
== 0xFFFFFFFF)
224 /* Get the brush colour. */
225 switch (GET_OPINDEX_FROM_ROP4(Rop4
))
227 case GET_OPINDEX_FROM_ROP3(PATCOPY
): SolidColor
= Brush
->iSolidColor
; break;
228 case GET_OPINDEX_FROM_ROP3(PATINVERT
): SolidColor
= Brush
->iSolidColor
; RasterOp
= VGA_XOR
; break;
229 case GET_OPINDEX_FROM_ROP3(WHITENESS
): SolidColor
= 0xF; break;
230 case GET_OPINDEX_FROM_ROP3(BLACKNESS
): SolidColor
= 0x0; break;
231 case GET_OPINDEX_FROM_ROP3(DSTINVERT
): SolidColor
= 0xF; RasterOp
= VGA_XOR
; break;
234 /* Select write mode 3. */
235 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05);
236 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x03);
238 /* Setup set/reset register. */
239 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x00);
240 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, (UCHAR
)SolidColor
);
242 /* Enable writes to all pixels. */
243 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08);
244 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0xFF);
246 /* Set up data rotate. */
247 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03);
248 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, RasterOp
);
250 /* Fill any pixels on the left which don't fall into a full row of eight. */
251 if ((DestRect
->left
% 8) != 0)
253 /* Disable writes to pixels outside of the destination rectangle. */
254 Mask
= (1 << (8 - (DestRect
->left
% 8))) - 1;
255 if ((DestRect
->right
- DestRect
->left
) < (8 - (DestRect
->left
% 8)))
256 Mask
&= ~((1 << (8 - (DestRect
->right
% 8))) - 1);
258 /* Write the same color to each pixel. */
259 Video
= (PUCHAR
)vidmem
+ DestRect
->top
* 80 + (DestRect
->left
>> 3);
260 for (i
= DestRect
->top
; i
< DestRect
->bottom
; i
++, Video
+= 80)
262 (VOID
)READ_REGISTER_UCHAR(Video
);
263 WRITE_REGISTER_UCHAR(Video
, Mask
);
266 /* Have we finished. */
267 if ((DestRect
->right
- DestRect
->left
) < (8 - (DestRect
->left
% 8)))
269 /* Restore write mode 2. */
270 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05);
271 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
273 /* Set up data rotate. */
274 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03);
275 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
281 /* Fill any whole rows of eight pixels. */
282 Left
= (DestRect
->left
+ 7) & ~0x7;
283 Length
= (DestRect
->right
>> 3) - (Left
>> 3);
284 for (i
= DestRect
->top
; i
< DestRect
->bottom
; i
++)
286 Video
= (PUCHAR
)vidmem
+ i
* 80 + (Left
>> 3);
287 for (j
= 0; j
< Length
; j
++, Video
++)
290 (VOID
)READ_REGISTER_UCHAR(Video
);
291 WRITE_REGISTER_UCHAR(Video
, 0xFF);
293 char volatile Temp
= *Video
;
300 /* Fill any pixels on the right which don't fall into a complete row. */
301 if ((DestRect
->right
% 8) != 0)
303 /* Disable writes to pixels outside the destination rectangle. */
304 Mask
= ~((1 << (8 - (DestRect
->right
% 8))) - 1);
306 Video
= (PUCHAR
)vidmem
+ DestRect
->top
* 80 + (DestRect
->right
>> 3);
307 for (i
= DestRect
->top
; i
< DestRect
->bottom
; i
++, Video
+= 80)
309 (VOID
)READ_REGISTER_UCHAR(Video
);
310 WRITE_REGISTER_UCHAR(Video
, Mask
);
314 /* Restore write mode 2. */
315 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05);
316 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
318 /* Set up data rotate. */
319 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03);
320 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
330 IN XLATEOBJ
* ColorTranslation
,
332 IN POINTL
* SourcePoint
,
333 IN POINTL
* MaskOrigin
,
335 IN POINTL
* BrushOrigin
,
338 PFN_VGABlt BltOperation
;
341 SourceType
= Source
->iType
;
343 if (SourceType
== STYPE_BITMAP
&& Dest
->iType
== STYPE_DEVICE
)
344 BltOperation
= DIBtoVGA
;
345 else if (SourceType
== STYPE_DEVICE
&& Dest
->iType
== STYPE_BITMAP
)
346 BltOperation
= VGAtoDIB
;
347 else if (SourceType
== STYPE_DEVICE
&& Dest
->iType
== STYPE_DEVICE
)
348 BltOperation
= VGAtoVGA
;
349 else if (SourceType
== STYPE_DEVBITMAP
&& Dest
->iType
== STYPE_DEVICE
)
350 BltOperation
= DFBtoVGA
;
351 else if (SourceType
== STYPE_DEVICE
&& Dest
->iType
== STYPE_DEVBITMAP
)
352 BltOperation
= VGAtoDFB
;
355 /* Punt blts not involving a device or a device-bitmap. */
359 BltOperation(Dest
, Source
, ColorTranslation
, DestRect
, SourcePoint
);
368 IN XLATEOBJ
* ColorTranslation
,
370 IN POINTL
* SourcePoint
,
371 IN POINTL
* MaskPoint
,
373 IN POINTL
* BrushPoint
,
376 LONG i
, j
, dx
, dy
, c8
;
379 dx
= DestRect
->right
- DestRect
->left
;
380 dy
= DestRect
->bottom
- DestRect
->top
;
382 if (ColorTranslation
== NULL
)
386 tMask
= Mask
->pvScan0
;
387 for (j
= 0; j
< dy
; j
++)
391 for (i
= 0; i
< dx
; i
++)
393 if((*lMask
& maskbit
[c8
]) != 0)
394 vgaPutPixel(DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
402 tMask
+= Mask
->lDelta
;
415 IN XLATEOBJ
*ColorTranslation
,
417 IN POINTL
*SourcePoint
,
418 IN POINTL
*MaskPoint
,
420 IN POINTL
*BrushPoint
,
423 PBLTRECTFUNC BltRectFunc
;
431 POINTL FinalSourcePoint
;
433 if (Source
&& SourcePoint
)
435 FinalSourcePoint
.x
= SourcePoint
->x
;
436 FinalSourcePoint
.y
= SourcePoint
->y
;
440 FinalSourcePoint
.x
= 0;
441 FinalSourcePoint
.y
= 0;
446 case ROP3_TO_ROP4(BLACKNESS
):
447 case ROP3_TO_ROP4(PATCOPY
):
448 case ROP3_TO_ROP4(WHITENESS
):
449 case ROP3_TO_ROP4(PATINVERT
):
450 case ROP3_TO_ROP4(DSTINVERT
):
451 BltRectFunc
= VGADDI_BltBrush
;
454 case ROP3_TO_ROP4(SRCCOPY
):
455 if (BMF_4BPP
== Source
->iBitmapFormat
&& BMF_4BPP
== Dest
->iBitmapFormat
)
456 BltRectFunc
= VGADDI_BltSrc
;
462 BltRectFunc
= VGADDI_BltMask
;
469 switch (NULL
== Clip
? DC_TRIVIAL
: Clip
->iDComplexity
)
472 Ret
= (*BltRectFunc
)(Dest
, Source
, Mask
, ColorTranslation
, DestRect
,
473 SourcePoint
, MaskPoint
, Brush
, BrushPoint
,
477 /* Clip the blt to the clip rectangle */
478 VGADDI_IntersectRect(&CombinedRect
, DestRect
, &(Clip
->rclBounds
));
479 Pt
.x
= FinalSourcePoint
.x
+ CombinedRect
.left
- DestRect
->left
;
480 Pt
.y
= FinalSourcePoint
.y
+ CombinedRect
.top
- DestRect
->top
;
481 Ret
= (*BltRectFunc
)(Dest
, Source
, Mask
, ColorTranslation
, &CombinedRect
,
482 &Pt
, MaskPoint
, Brush
, BrushPoint
,
489 if (DestRect
->top
<= FinalSourcePoint
.y
)
490 Direction
= DestRect
->left
< FinalSourcePoint
.y
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
492 Direction
= DestRect
->left
< FinalSourcePoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
498 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, Direction
, 0);
501 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
503 for (i
= 0; i
< RectEnum
.c
; i
++)
505 VGADDI_IntersectRect(&CombinedRect
, DestRect
, RectEnum
.arcl
+ i
);
506 Pt
.x
= FinalSourcePoint
.x
+ CombinedRect
.left
- DestRect
->left
;
507 Pt
.y
= FinalSourcePoint
.y
+ CombinedRect
.top
- DestRect
->top
;
508 Ret
= (*BltRectFunc
)(Dest
, Source
, Mask
, ColorTranslation
, &CombinedRect
,
509 &Pt
, MaskPoint
, Brush
, BrushPoint
, rop4
) &&