- make vga buildable on msvc.
[reactos.git] / reactos / drivers / video / displays / vga / objects / bitblt.c
1 #include "../vgaddi.h"
2 #include "../vgavideo/vgavideo.h"
3 #include "brush.h"
4 #include "bitblt.h"
5
6 #define NDEBUG
7 #include <debug.h>
8
9 typedef BOOL (*PFN_VGABlt)(SURFOBJ*, SURFOBJ*, XLATEOBJ*, RECTL*, POINTL*);
10 typedef BOOL (STDCALL *PBLTRECTFUNC)(SURFOBJ* OutputObj,
11 SURFOBJ* InputObj,
12 SURFOBJ* Mask,
13 XLATEOBJ* ColorTranslation,
14 RECTL* OutputRect,
15 POINTL* InputPoint,
16 POINTL* MaskOrigin,
17 BRUSHOBJ* Brush,
18 POINTL* BrushOrigin,
19 ROP4 Rop4);
20
21 static BOOL FASTCALL VGADDI_IntersectRect(RECTL* prcDst, RECTL* prcSrc1, RECTL* prcSrc2)
22 {
23 static const RECTL rclEmpty = { 0, 0, 0, 0 };
24
25 prcDst->left = max(prcSrc1->left, prcSrc2->left);
26 prcDst->right = min(prcSrc1->right, prcSrc2->right);
27
28 if (prcDst->left < prcDst->right)
29 {
30 prcDst->top = max(prcSrc1->top, prcSrc2->top);
31 prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
32
33 if (prcDst->top < prcDst->bottom) return(TRUE);
34 }
35
36 *prcDst = rclEmpty;
37
38 return(FALSE);
39 }
40
41 void DIB_BltToVGA_Fixed(int x, int y, int w, int h, void *b, int Source_lDelta, int mod);
42
43 BOOL
44 DIBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
45 RECTL *DestRect, POINTL *SourcePoint)
46 {
47 LONG dx, dy;
48
49 dx = DestRect->right - DestRect->left;
50 dy = DestRect->bottom - DestRect->top;
51
52 if (NULL == ColorTranslation || 0 != (ColorTranslation->flXlate & XO_TRIVIAL))
53 {
54 DIB_BltToVGA(DestRect->left, DestRect->top, dx, dy,
55 (PVOID)((ULONG_PTR)Source->pvScan0 + SourcePoint->y * Source->lDelta + (SourcePoint->x >> 1)),
56 Source->lDelta, SourcePoint->x % 2);
57 }
58 else
59 {
60 /* Perform color translation */
61 DIB_BltToVGAWithXlate(DestRect->left, DestRect->top, dx, dy,
62 (PVOID)((ULONG_PTR)Source->pvScan0 + SourcePoint->y * Source->lDelta + (SourcePoint->x >> 1)),
63 Source->lDelta, ColorTranslation);
64 }
65 return FALSE;
66 }
67
68 BOOL
69 VGAtoDIB(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
70 RECTL *DestRect, POINTL *SourcePoint)
71 {
72 LONG i, j, dx, dy;
73 BYTE *GDIpos, *initial;
74
75 // Used by the temporary DFB
76 DEVSURF DestDevSurf;
77
78 // FIXME: Optimize to retrieve entire bytes at a time (see /display/vgavideo/vgavideo.c:vgaGetByte)
79
80 GDIpos = Dest->pvScan0 /* + (DestRect->top * Dest->lDelta) + (DestRect->left >> 1) */ ;
81 dx = DestRect->right - DestRect->left;
82 dy = DestRect->bottom - DestRect->top;
83
84 if(ColorTranslation == NULL)
85 {
86 // Prepare a Dest Dev Target and copy from the DFB to the DIB
87 DestDevSurf.NextScan = Dest->lDelta;
88 DestDevSurf.StartBmp = Dest->pvScan0;
89
90 DIB_BltFromVGA(SourcePoint->x, SourcePoint->y, dx, dy, Dest->pvScan0, Dest->lDelta);
91
92 } else {
93 // Color translation
94 for(j=SourcePoint->y; j<SourcePoint->y+dy; j++)
95 {
96 initial = GDIpos;
97 for(i=SourcePoint->x; i<SourcePoint->x+dx; i++)
98 {
99 *GDIpos = XLATEOBJ_iXlate(ColorTranslation, vgaGetPixel(i, j));
100 GDIpos+=1;
101 }
102 GDIpos = initial + Dest->lDelta;
103 }
104 }
105 return FALSE;
106 }
107
108 BOOL
109 DFBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
110 RECTL *DestRect, POINTL *SourcePoint)
111 {
112 return FALSE;
113 // Do DFBs need color translation??
114 }
115
116 BOOL
117 VGAtoDFB(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
118 RECTL *DestRect, POINTL *SourcePoint)
119 {
120 return FALSE;
121 // Do DFBs need color translation??
122 }
123
124 BOOL
125 VGAtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
126 RECTL *DestRect, POINTL *SourcePoint)
127 {
128 LONG i, i2, j, dx, dy, alterx, altery;
129 //LARGE_INTEGER Start, End; // for performance measurement only
130 static char buf[640];
131
132 // Calculate deltas
133
134 dx = DestRect->right - DestRect->left;
135 dy = DestRect->bottom - DestRect->top;
136
137 alterx = DestRect->left - SourcePoint->x;
138 altery = DestRect->top - SourcePoint->y;
139
140 //KeQueryTickCount ( &Start );
141
142 i = SourcePoint->x;
143 i2 = i + alterx;
144
145 if (SourcePoint->y >= DestRect->top)
146 {
147 for(j=SourcePoint->y; j<SourcePoint->y+dy; j++)
148 {
149 LONG j2 = j + altery;
150 vgaReadScan ( i, j, dx, buf );
151 vgaWriteScan ( i2, j2, dx, buf );
152 }
153 }
154 else
155 {
156 for(j=(SourcePoint->y+dy-1); j>=SourcePoint->y; j--)
157 {
158 LONG j2 = j + altery;
159 vgaReadScan ( i, j, dx, buf );
160 vgaWriteScan ( i2, j2, dx, buf );
161 }
162 }
163
164 //KeQueryTickCount ( &End );
165 //DbgPrint ( "VgaBitBlt timing: %lu\n", (ULONG)(End.QuadPart-Start.QuadPart) );
166
167 return TRUE;
168 }
169
170 BOOL STDCALL
171 VGADDI_BltBrush(SURFOBJ* Dest, SURFOBJ* Source, SURFOBJ* MaskSurf,
172 XLATEOBJ* ColorTranslation, RECTL* DestRect,
173 POINTL* SourcePoint, POINTL* MaskPoint,
174 BRUSHOBJ* Brush, POINTL* BrushPoint, ROP4 Rop4)
175 {
176 UCHAR SolidColor = 0;
177 LONG Left;
178 LONG Length;
179 PUCHAR Video;
180 UCHAR Mask;
181 INT i, j;
182 ULONG RasterOp = VGA_NORMAL;
183
184 /* Punt brush blts to non-device surfaces. */
185 if (Dest->iType != STYPE_DEVICE)
186 {
187 return(FALSE);
188 }
189
190 /* Punt pattern fills. */
191 if ((GET_OPINDEX_FROM_ROP4(Rop4) == GET_OPINDEX_FROM_ROP3(PATCOPY)
192 || GET_OPINDEX_FROM_ROP4(Rop4) == GET_OPINDEX_FROM_ROP3(PATINVERT)) &&
193 Brush->iSolidColor == 0xFFFFFFFF)
194 {
195 return(FALSE);
196 }
197
198 /* Get the brush colour. */
199 switch (GET_OPINDEX_FROM_ROP4(Rop4))
200 {
201 case GET_OPINDEX_FROM_ROP3(PATCOPY): SolidColor = Brush->iSolidColor; break;
202 case GET_OPINDEX_FROM_ROP3(PATINVERT): SolidColor = Brush->iSolidColor; RasterOp = VGA_XOR; break;
203 case GET_OPINDEX_FROM_ROP3(WHITENESS): SolidColor = 0xF; break;
204 case GET_OPINDEX_FROM_ROP3(BLACKNESS): SolidColor = 0x0; break;
205 case GET_OPINDEX_FROM_ROP3(DSTINVERT): SolidColor = 0xF; RasterOp = VGA_XOR; break;
206 }
207
208 /* Select write mode 3. */
209 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05);
210 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x03);
211
212 /* Setup set/reset register. */
213 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x00);
214 WRITE_PORT_UCHAR((PUCHAR)GRA_D, (UCHAR)SolidColor);
215
216 /* Enable writes to all pixels. */
217 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08);
218 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF);
219
220 /* Set up data rotate. */
221 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03);
222 WRITE_PORT_UCHAR((PUCHAR)GRA_D, RasterOp);
223
224 /* Fill any pixels on the left which don't fall into a full row of eight. */
225 if ((DestRect->left % 8) != 0)
226 {
227 /* Disable writes to pixels outside of the destination rectangle. */
228 Mask = (1 << (8 - (DestRect->left % 8))) - 1;
229 if ((DestRect->right - DestRect->left) < (8 - (DestRect->left % 8)))
230 {
231 Mask &= ~((1 << (8 - (DestRect->right % 8))) - 1);
232 }
233
234 /* Write the same color to each pixel. */
235 Video = (PUCHAR)vidmem + DestRect->top * 80 + (DestRect->left >> 3);
236 for (i = DestRect->top; i < DestRect->bottom; i++, Video+=80)
237 {
238 (VOID)READ_REGISTER_UCHAR(Video);
239 WRITE_REGISTER_UCHAR(Video, Mask);
240 }
241
242 /* Have we finished. */
243 if ((DestRect->right - DestRect->left) < (8 - (DestRect->left % 8)))
244 {
245 /* Restore write mode 2. */
246 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05);
247 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
248
249 /* Set up data rotate. */
250 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03);
251 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
252
253 return TRUE;
254 }
255 }
256
257 /* Fill any whole rows of eight pixels. */
258 Left = (DestRect->left + 7) & ~0x7;
259 Length = (DestRect->right >> 3) - (Left >> 3);
260 for (i = DestRect->top; i < DestRect->bottom; i++)
261 {
262 Video = (PUCHAR)vidmem + i * 80 + (Left >> 3);
263 for (j = 0; j < Length; j++, Video++)
264 {
265 #if 0
266 (VOID)READ_REGISTER_UCHAR(Video);
267 WRITE_REGISTER_UCHAR(Video, 0xFF);
268 #else
269 char volatile Temp = *Video;
270 Temp |= 0;
271 *Video = 0xFF;
272 #endif
273 }
274 }
275
276 /* Fill any pixels on the right which don't fall into a complete row. */
277 if ((DestRect->right % 8) != 0)
278 {
279 /* Disable writes to pixels outside the destination rectangle. */
280 Mask = ~((1 << (8 - (DestRect->right % 8))) - 1);
281
282 Video = (PUCHAR)vidmem + DestRect->top * 80 + (DestRect->right >> 3);
283 for (i = DestRect->top; i < DestRect->bottom; i++, Video+=80)
284 {
285 (VOID)READ_REGISTER_UCHAR(Video);
286 WRITE_REGISTER_UCHAR(Video, Mask);
287 }
288 }
289
290 /* Restore write mode 2. */
291 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05);
292 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
293
294 /* Set up data rotate. */
295 WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03);
296 WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
297
298 return TRUE;
299 }
300
301 BOOL STDCALL
302 VGADDI_BltSrc(SURFOBJ* Dest, SURFOBJ* Source, SURFOBJ* Mask,
303 XLATEOBJ* ColorTranslation, RECTL* DestRect, POINTL* SourcePoint,
304 POINTL* MaskOrigin, BRUSHOBJ* Brush, POINTL* BrushOrigin, ROP4 Rop4)
305 {
306 PFN_VGABlt BltOperation;
307 ULONG SourceType;
308
309 SourceType = Source->iType;
310
311 if (SourceType == STYPE_BITMAP && Dest->iType == STYPE_DEVICE)
312 {
313 BltOperation = DIBtoVGA;
314 }
315 else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_BITMAP)
316 {
317 BltOperation = VGAtoDIB;
318 }
319 else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_DEVICE)
320 {
321 BltOperation = VGAtoVGA;
322 }
323 else if (SourceType == STYPE_DEVBITMAP && Dest->iType == STYPE_DEVICE)
324 {
325 BltOperation = DFBtoVGA;
326 }
327 else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_DEVBITMAP)
328 {
329 BltOperation = VGAtoDFB;
330 }
331 else
332 {
333 /* Punt blts not involving a device or a device-bitmap. */
334 return(FALSE);
335 }
336
337 BltOperation(Dest, Source, ColorTranslation, DestRect, SourcePoint);
338 return(TRUE);
339 }
340
341 BOOL STDCALL
342 VGADDI_BltMask(SURFOBJ* Dest, SURFOBJ* Source, SURFOBJ* Mask,
343 XLATEOBJ* ColorTranslation, RECTL* DestRect,
344 POINTL* SourcePoint, POINTL* MaskPoint, BRUSHOBJ* Brush,
345 POINTL* BrushPoint, ROP4 Rop4)
346 {
347 LONG i, j, dx, dy, c8;
348 BYTE *tMask, *lMask;
349
350 dx = DestRect->right - DestRect->left;
351 dy = DestRect->bottom - DestRect->top;
352
353 if (ColorTranslation == NULL)
354 {
355 if (Mask != NULL)
356 {
357 tMask = Mask->pvScan0;
358 for (j=0; j<dy; j++)
359 {
360 lMask = tMask;
361 c8 = 0;
362 for (i=0; i<dx; i++)
363 {
364 if((*lMask & maskbit[c8]) != 0)
365 {
366 vgaPutPixel(DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
367 }
368 c8++;
369 if(c8 == 8) { lMask++; c8=0; }
370 }
371 tMask += Mask->lDelta;
372 }
373 }
374 }
375 return TRUE;
376 }
377
378 BOOL STDCALL
379 DrvBitBlt(SURFOBJ *Dest,
380 SURFOBJ *Source,
381 SURFOBJ *Mask,
382 CLIPOBJ *Clip,
383 XLATEOBJ *ColorTranslation,
384 RECTL *DestRect,
385 POINTL *SourcePoint,
386 POINTL *MaskPoint,
387 BRUSHOBJ *Brush,
388 POINTL *BrushPoint,
389 ROP4 rop4)
390 {
391 PBLTRECTFUNC BltRectFunc;
392 RECTL CombinedRect;
393 BOOL Ret = FALSE;
394 RECT_ENUM RectEnum;
395 BOOL EnumMore;
396 unsigned i;
397 POINTL Pt;
398 ULONG Direction;
399
400 switch (rop4)
401 {
402 case ROP3_TO_ROP4(BLACKNESS):
403 case ROP3_TO_ROP4(PATCOPY):
404 case ROP3_TO_ROP4(WHITENESS):
405 case ROP3_TO_ROP4(PATINVERT):
406 case ROP3_TO_ROP4(DSTINVERT):
407 BltRectFunc = VGADDI_BltBrush;
408 break;
409
410 case ROP3_TO_ROP4(SRCCOPY):
411 if (BMF_4BPP == Source->iBitmapFormat && BMF_4BPP == Dest->iBitmapFormat)
412 {
413 BltRectFunc = VGADDI_BltSrc;
414 }
415 else
416 {
417 return FALSE;
418 }
419 break;
420
421 case R4_MASK:
422 BltRectFunc = VGADDI_BltMask;
423 break;
424
425 default:
426 return FALSE;
427 }
428
429 switch(NULL == Clip ? DC_TRIVIAL : Clip->iDComplexity)
430 {
431 case DC_TRIVIAL:
432 Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, DestRect,
433 SourcePoint, MaskPoint, Brush, BrushPoint,
434 rop4);
435 break;
436 case DC_RECT:
437 // Clip the blt to the clip rectangle
438 VGADDI_IntersectRect(&CombinedRect, DestRect, &(Clip->rclBounds));
439 Pt.x = SourcePoint->x + CombinedRect.left - DestRect->left;
440 Pt.y = SourcePoint->y + CombinedRect.top - DestRect->top;
441 Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, &CombinedRect,
442 &Pt, MaskPoint, Brush, BrushPoint,
443 rop4);
444 break;
445 case DC_COMPLEX:
446 Ret = TRUE;
447 if (Dest == Source)
448 {
449 if (DestRect->top <= SourcePoint->y)
450 {
451 Direction = DestRect->left < SourcePoint->x ? CD_RIGHTDOWN : CD_LEFTDOWN;
452 }
453 else
454 {
455 Direction = DestRect->left < SourcePoint->x ? CD_RIGHTUP : CD_LEFTUP;
456 }
457 }
458 else
459 {
460 Direction = CD_ANY;
461 }
462 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, Direction, 0);
463 do
464 {
465 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
466
467 for (i = 0; i < RectEnum.c; i++)
468 {
469 VGADDI_IntersectRect(&CombinedRect, DestRect, RectEnum.arcl + i);
470 Pt.x = SourcePoint->x + CombinedRect.left - DestRect->left;
471 Pt.y = SourcePoint->y + CombinedRect.top - DestRect->top;
472 Ret = (*BltRectFunc)(Dest, Source, Mask, ColorTranslation, &CombinedRect,
473 &Pt, MaskPoint, Brush, BrushPoint, rop4) &&
474 Ret;
475 }
476 }
477 while (EnumMore);
478 break;
479 }
480
481 return Ret;
482 }