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
11 typedef BOOL (*PFN_VGABlt
)(SURFOBJ
*, SURFOBJ
*, XLATEOBJ
*, RECTL
*, POINTL
*);
12 typedef BOOL (APIENTRY
*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
15 XLATEOBJ
* ColorTranslation
,
23 static BOOL FASTCALL
VGADDI_IntersectRect(
28 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
30 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
31 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
33 if (prcDst
->left
< prcDst
->right
)
35 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
36 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
38 if (prcDst
->top
< prcDst
->bottom
) return(TRUE
);
46 void DIB_BltToVGA_Fixed(int x
, int y
, int w
, int h
, void *b
, int Source_lDelta
, int mod
);
52 IN XLATEOBJ
*ColorTranslation
,
54 IN POINTL
*SourcePoint
)
58 dx
= DestRect
->right
- DestRect
->left
;
59 dy
= DestRect
->bottom
- DestRect
->top
;
61 if (NULL
== ColorTranslation
|| 0 != (ColorTranslation
->flXlate
& XO_TRIVIAL
))
63 DIB_BltToVGA(DestRect
->left
, DestRect
->top
, dx
, dy
,
64 (PVOID
)((ULONG_PTR
)Source
->pvScan0
+ SourcePoint
->y
* Source
->lDelta
+ (SourcePoint
->x
>> 1)),
65 Source
->lDelta
, SourcePoint
->x
% 2);
69 /* Perform color translation */
70 DIB_BltToVGAWithXlate(DestRect
->left
, DestRect
->top
, dx
, dy
,
71 (PVOID
)((ULONG_PTR
)Source
->pvScan0
+ SourcePoint
->y
* Source
->lDelta
+ (SourcePoint
->x
>> 1)),
72 Source
->lDelta
, ColorTranslation
);
81 IN XLATEOBJ
*ColorTranslation
,
83 IN POINTL
*SourcePoint
)
86 UCHAR
*GDIpos
, *initial
;
88 /* Used by the temporary DFB */
89 //DEVSURF DestDevSurf;
91 /* FIXME: Optimize to retrieve entire bytes at a time (see ../vgavideo/vgavideo.c:vgaGetByte) */
93 GDIpos
= Dest
->pvScan0
/* + (DestRect->top * Dest->lDelta) + (DestRect->left >> 1) */ ;
94 dx
= DestRect
->right
- DestRect
->left
;
95 dy
= DestRect
->bottom
- DestRect
->top
;
97 if (ColorTranslation
== NULL
)
99 /* Prepare a Dest Dev Target and copy from the DFB to the DIB */
100 //DestDevSurf.NextScan = Dest->lDelta;
101 //DestDevSurf.StartBmp = Dest->pvScan0;
103 DIB_BltFromVGA(SourcePoint
->x
, SourcePoint
->y
, dx
, dy
, Dest
->pvScan0
, Dest
->lDelta
);
107 /* Color translation */
108 for (j
= SourcePoint
->y
; j
< SourcePoint
->y
+ dy
; j
++)
111 for (i
= SourcePoint
->x
; i
< SourcePoint
->x
+ dx
; i
++)
113 *GDIpos
= XLATEOBJ_iXlate(ColorTranslation
, vgaGetPixel(i
, j
));
116 GDIpos
= initial
+ Dest
->lDelta
;
126 IN XLATEOBJ
*ColorTranslation
,
128 IN POINTL
*SourcePoint
)
130 /* Do DFBs need color translation?? */
138 IN XLATEOBJ
*ColorTranslation
,
140 IN POINTL
*SourcePoint
)
142 /* Do DFBs need color translation?? */
150 IN XLATEOBJ
*ColorTranslation
,
152 IN POINTL
*SourcePoint
)
154 LONG i
, i2
, j
, dx
, dy
, alterx
, altery
;
155 static char buf
[SCREEN_X
];
157 /* Calculate deltas */
158 dx
= DestRect
->right
- DestRect
->left
;
159 dy
= DestRect
->bottom
- DestRect
->top
;
161 alterx
= DestRect
->left
- SourcePoint
->x
;
162 altery
= DestRect
->top
- SourcePoint
->y
;
167 if (SourcePoint
->y
>= DestRect
->top
)
169 for (j
= SourcePoint
->y
; j
< SourcePoint
->y
+ dy
; j
++)
171 LONG j2
= j
+ altery
;
172 vgaReadScan ( i
, j
, dx
, buf
);
173 vgaWriteScan ( i2
, j2
, dx
, buf
);
178 for(j
= (SourcePoint
->y
+ dy
- 1); j
>= SourcePoint
->y
; j
--)
180 LONG j2
= j
+ altery
;
181 vgaReadScan ( i
, j
, dx
, buf
);
182 vgaWriteScan ( i2
, j2
, dx
, buf
);
193 IN SURFOBJ
* MaskSurf
,
194 IN XLATEOBJ
* ColorTranslation
,
196 IN POINTL
* SourcePoint
,
197 IN POINTL
* MaskPoint
,
199 IN POINTL
* BrushPoint
,
202 UCHAR SolidColor
= 0;
208 ULONG RasterOp
= VGA_NORMAL
;
210 /* Punt brush blts to non-device surfaces. */
211 if (Dest
->iType
!= STYPE_DEVICE
)
214 /* Punt pattern fills. */
215 if ((GET_OPINDEX_FROM_ROP4(Rop4
) == GET_OPINDEX_FROM_ROP3(PATCOPY
)
216 || GET_OPINDEX_FROM_ROP4(Rop4
) == GET_OPINDEX_FROM_ROP3(PATINVERT
)) &&
217 Brush
->iSolidColor
== 0xFFFFFFFF)
222 /* Get the brush colour. */
223 switch (GET_OPINDEX_FROM_ROP4(Rop4
))
225 case GET_OPINDEX_FROM_ROP3(PATCOPY
): SolidColor
= Brush
->iSolidColor
; break;
226 case GET_OPINDEX_FROM_ROP3(PATINVERT
): SolidColor
= Brush
->iSolidColor
; RasterOp
= VGA_XOR
; break;
227 case GET_OPINDEX_FROM_ROP3(WHITENESS
): SolidColor
= 0xF; break;
228 case GET_OPINDEX_FROM_ROP3(BLACKNESS
): SolidColor
= 0x0; break;
229 case GET_OPINDEX_FROM_ROP3(DSTINVERT
): SolidColor
= 0xF; RasterOp
= VGA_XOR
; break;
232 /* Select write mode 3. */
233 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05);
234 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x03);
236 /* Setup set/reset register. */
237 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x00);
238 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, (UCHAR
)SolidColor
);
240 /* Enable writes to all pixels. */
241 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x08);
242 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0xFF);
244 /* Set up data rotate. */
245 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03);
246 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, RasterOp
);
248 /* Fill any pixels on the left which don't fall into a full row of eight. */
249 if ((DestRect
->left
% 8) != 0)
251 /* Disable writes to pixels outside of the destination rectangle. */
252 Mask
= (1 << (8 - (DestRect
->left
% 8))) - 1;
253 if ((DestRect
->right
- DestRect
->left
) < (8 - (DestRect
->left
% 8)))
254 Mask
&= ~((1 << (8 - (DestRect
->right
% 8))) - 1);
256 /* Write the same color to each pixel. */
257 Video
= (PUCHAR
)vidmem
+ DestRect
->top
* 80 + (DestRect
->left
>> 3);
258 for (i
= DestRect
->top
; i
< DestRect
->bottom
; i
++, Video
+= 80)
260 (VOID
)READ_REGISTER_UCHAR(Video
);
261 WRITE_REGISTER_UCHAR(Video
, Mask
);
264 /* Have we finished. */
265 if ((DestRect
->right
- DestRect
->left
) < (8 - (DestRect
->left
% 8)))
267 /* Restore write mode 2. */
268 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05);
269 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
271 /* Set up data rotate. */
272 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03);
273 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
279 /* Fill any whole rows of eight pixels. */
280 Left
= (DestRect
->left
+ 7) & ~0x7;
281 Length
= (DestRect
->right
>> 3) - (Left
>> 3);
282 for (i
= DestRect
->top
; i
< DestRect
->bottom
; i
++)
284 Video
= (PUCHAR
)vidmem
+ i
* 80 + (Left
>> 3);
285 for (j
= 0; j
< Length
; j
++, Video
++)
288 (VOID
)READ_REGISTER_UCHAR(Video
);
289 WRITE_REGISTER_UCHAR(Video
, 0xFF);
291 char volatile Temp
= *Video
;
298 /* Fill any pixels on the right which don't fall into a complete row. */
299 if ((DestRect
->right
% 8) != 0)
301 /* Disable writes to pixels outside the destination rectangle. */
302 Mask
= ~((1 << (8 - (DestRect
->right
% 8))) - 1);
304 Video
= (PUCHAR
)vidmem
+ DestRect
->top
* 80 + (DestRect
->right
>> 3);
305 for (i
= DestRect
->top
; i
< DestRect
->bottom
; i
++, Video
+= 80)
307 (VOID
)READ_REGISTER_UCHAR(Video
);
308 WRITE_REGISTER_UCHAR(Video
, Mask
);
312 /* Restore write mode 2. */
313 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x05);
314 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x02);
316 /* Set up data rotate. */
317 WRITE_PORT_UCHAR((PUCHAR
)GRA_I
, 0x03);
318 WRITE_PORT_UCHAR((PUCHAR
)GRA_D
, 0x00);
328 IN XLATEOBJ
* ColorTranslation
,
330 IN POINTL
* SourcePoint
,
331 IN POINTL
* MaskOrigin
,
333 IN POINTL
* BrushOrigin
,
336 PFN_VGABlt BltOperation
;
339 SourceType
= Source
->iType
;
341 if (SourceType
== STYPE_BITMAP
&& Dest
->iType
== STYPE_DEVICE
)
342 BltOperation
= DIBtoVGA
;
343 else if (SourceType
== STYPE_DEVICE
&& Dest
->iType
== STYPE_BITMAP
)
344 BltOperation
= VGAtoDIB
;
345 else if (SourceType
== STYPE_DEVICE
&& Dest
->iType
== STYPE_DEVICE
)
346 BltOperation
= VGAtoVGA
;
347 else if (SourceType
== STYPE_DEVBITMAP
&& Dest
->iType
== STYPE_DEVICE
)
348 BltOperation
= DFBtoVGA
;
349 else if (SourceType
== STYPE_DEVICE
&& Dest
->iType
== STYPE_DEVBITMAP
)
350 BltOperation
= VGAtoDFB
;
353 /* Punt blts not involving a device or a device-bitmap. */
357 BltOperation(Dest
, Source
, ColorTranslation
, DestRect
, SourcePoint
);
366 IN XLATEOBJ
* ColorTranslation
,
368 IN POINTL
* SourcePoint
,
369 IN POINTL
* MaskPoint
,
371 IN POINTL
* BrushPoint
,
374 LONG i
, j
, dx
, dy
, c8
;
377 dx
= DestRect
->right
- DestRect
->left
;
378 dy
= DestRect
->bottom
- DestRect
->top
;
380 if (ColorTranslation
== NULL
)
384 tMask
= Mask
->pvScan0
;
385 for (j
= 0; j
< dy
; j
++)
389 for (i
= 0; i
< dx
; i
++)
391 if((*lMask
& maskbit
[c8
]) != 0)
392 vgaPutPixel(DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
400 tMask
+= Mask
->lDelta
;
413 IN XLATEOBJ
*ColorTranslation
,
415 IN POINTL
*SourcePoint
,
416 IN POINTL
*MaskPoint
,
418 IN POINTL
*BrushPoint
,
421 PBLTRECTFUNC BltRectFunc
;
429 POINTL FinalSourcePoint
;
431 if (Source
&& SourcePoint
)
433 FinalSourcePoint
.x
= SourcePoint
->x
;
434 FinalSourcePoint
.y
= SourcePoint
->y
;
438 FinalSourcePoint
.x
= 0;
439 FinalSourcePoint
.y
= 0;
444 case ROP3_TO_ROP4(BLACKNESS
):
445 case ROP3_TO_ROP4(PATCOPY
):
446 case ROP3_TO_ROP4(WHITENESS
):
447 case ROP3_TO_ROP4(PATINVERT
):
448 case ROP3_TO_ROP4(DSTINVERT
):
449 BltRectFunc
= VGADDI_BltBrush
;
452 case ROP3_TO_ROP4(SRCCOPY
):
453 if (BMF_4BPP
== Source
->iBitmapFormat
&& BMF_4BPP
== Dest
->iBitmapFormat
)
454 BltRectFunc
= VGADDI_BltSrc
;
460 BltRectFunc
= VGADDI_BltMask
;
467 switch (NULL
== Clip
? DC_TRIVIAL
: Clip
->iDComplexity
)
470 Ret
= (*BltRectFunc
)(Dest
, Source
, Mask
, ColorTranslation
, DestRect
,
471 SourcePoint
, MaskPoint
, Brush
, BrushPoint
,
475 /* Clip the blt to the clip rectangle */
476 VGADDI_IntersectRect(&CombinedRect
, DestRect
, &(Clip
->rclBounds
));
477 Pt
.x
= FinalSourcePoint
.x
+ CombinedRect
.left
- DestRect
->left
;
478 Pt
.y
= FinalSourcePoint
.y
+ CombinedRect
.top
- DestRect
->top
;
479 Ret
= (*BltRectFunc
)(Dest
, Source
, Mask
, ColorTranslation
, &CombinedRect
,
480 &Pt
, MaskPoint
, Brush
, BrushPoint
,
487 if (DestRect
->top
<= FinalSourcePoint
.y
)
488 Direction
= DestRect
->left
< FinalSourcePoint
.y
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
490 Direction
= DestRect
->left
< FinalSourcePoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
496 CLIPOBJ_cEnumStart(Clip
, FALSE
, CT_RECTANGLES
, Direction
, 0);
499 EnumMore
= CLIPOBJ_bEnum(Clip
, (ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
501 for (i
= 0; i
< RectEnum
.c
; i
++)
503 VGADDI_IntersectRect(&CombinedRect
, DestRect
, RectEnum
.arcl
+ i
);
504 Pt
.x
= FinalSourcePoint
.x
+ CombinedRect
.left
- DestRect
->left
;
505 Pt
.y
= FinalSourcePoint
.y
+ CombinedRect
.top
- DestRect
->top
;
506 Ret
= (*BltRectFunc
)(Dest
, Source
, Mask
, ColorTranslation
, &CombinedRect
,
507 &Pt
, MaskPoint
, Brush
, BrushPoint
, rop4
) &&