:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / dd / vga / display / objects / bitblt.c
1 #include <ntddk.h>
2 #define NDEBUG
3 #include <debug.h>
4 #include "../vgaddi.h"
5 #include "../vgavideo/vgavideo.h"
6 #include "brush.h"
7 #include "bitblt.h"
8
9 typedef BOOL (*PFN_VGABlt)(SURFOBJ*, SURFOBJ*, XLATEOBJ*, RECTL*, POINTL*);
10
11 BOOL 
12 DIBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
13          RECTL *DestRect, POINTL *SourcePoint)
14 {
15   LONG i, j, dx, dy, alterx, altery, idxColor, RGBulong = 0, c8;
16   BYTE  *GDIpos, *initial, *tMask, *lMask;
17
18   GDIpos = Source->pvBits;
19   
20   dx = DestRect->right  - DestRect->left;
21   dy = DestRect->bottom - DestRect->top;
22   
23   alterx = abs(SourcePoint->x - DestRect->left);
24   altery = abs(SourcePoint->y - DestRect->top);
25
26   if (ColorTranslation == NULL)
27     {      
28       DIB_BltToVGA(DestRect->left, DestRect->top, dx, dy, Source->pvBits, 
29                    Source->lDelta);
30     } 
31   else
32     {
33       /* Perform color translation */
34       for (j = SourcePoint->y; j < SourcePoint->y+dy; j++)
35         {
36           initial = GDIpos;
37           
38           for (i=SourcePoint->x; i<SourcePoint->x+dx; i++)
39             {
40               idxColor = XLATEOBJ_iXlate(ColorTranslation, *GDIpos);
41               vgaPutPixel(i+alterx, j+altery, idxColor);
42               GDIpos+=1;
43             }
44           GDIpos = initial + Source->lDelta;
45         }
46     }
47 }
48
49 BOOL 
50 VGAtoDIB(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
51          RECTL *DestRect, POINTL *SourcePoint)
52 {
53   LONG i, j, dx, dy, RGBulong;
54   BYTE  *GDIpos, *initial, idxColor;
55   
56   // Used by the temporary DFB
57   PDEVSURF      TargetSurf;
58   DEVSURF       DestDevSurf;
59   PSURFOBJ      TargetBitmapSurf;
60   HBITMAP       hTargetBitmap;
61   SIZEL         InterSize;
62   POINTL        ZeroPoint;
63
64   // FIXME: Optimize to retrieve entire bytes at a time (see /display/vgavideo/vgavideo.c:vgaGetByte)
65
66   GDIpos = Dest->pvBits /* + (DestRect->top * Dest->lDelta) + (DestRect->left >> 1) */ ;
67   dx = DestRect->right  - DestRect->left;
68   dy = DestRect->bottom - DestRect->top;
69
70   if(ColorTranslation == NULL)
71   {
72     // Prepare a Dest Dev Target and copy from the DFB to the DIB
73     DestDevSurf.NextScan = Dest->lDelta;
74     DestDevSurf.StartBmp = Dest->pvScan0;
75
76     DIB_BltFromVGA(SourcePoint->x, SourcePoint->y, dx, dy, Dest->pvBits, Dest->lDelta);
77
78   } else {
79     // Color translation
80     for(j=SourcePoint->y; j<SourcePoint->y+dy; j++)
81     {
82        initial = GDIpos;
83        for(i=SourcePoint->x; i<SourcePoint->x+dx; i++)
84        {
85          *GDIpos = XLATEOBJ_iXlate(ColorTranslation, vgaGetPixel(i, j));
86          GDIpos+=1;
87        }
88        GDIpos = initial + Dest->lDelta;
89     }
90   }
91 }
92
93 BOOL 
94 DFBtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
95          RECTL *DestRect, POINTL *SourcePoint)
96 {
97   // Do DFBs need color translation??
98 }
99
100 BOOL 
101 VGAtoDFB(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
102          RECTL *DestRect, POINTL *SourcePoint)
103 {
104   // Do DFBs need color translation??
105 }
106
107 BOOL 
108 VGAtoVGA(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
109          RECTL *DestRect, POINTL *SourcePoint)
110 {
111   // FIXME: Use fast blts instead of get and putpixels
112
113   int i, j, dx, dy, alterx, altery, BltDirection;
114
115   // Calculate deltas
116
117   dx = DestRect->right  - DestRect->left;
118   dy = DestRect->bottom - DestRect->top;
119
120   alterx = abs(SourcePoint->x - DestRect->left);
121   altery = abs(SourcePoint->y - DestRect->top);
122
123   // Determine bltting direction
124   // FIXME: should we perhaps make this an EngXxx function? Determining
125   // direction is probably used whenever the surfaces are the same (not
126   // just VGA screen)
127   if (SourcePoint->y >= DestRect->top)
128   {
129     if (SourcePoint->x >= DestRect->left)
130     {
131       BltDirection = CD_RIGHTDOWN;
132     }
133     else
134     {
135       BltDirection = CD_LEFTDOWN;
136     }
137   }
138   else
139   {
140     if (SourcePoint->x >= DestRect->left)
141     {
142       BltDirection = CD_RIGHTUP;
143     }
144     else
145     {
146       BltDirection = CD_LEFTUP;
147     }
148   }
149
150   // Do the VGA to VGA BitBlt
151   // FIXME: Right now we're only doing CN_LEFTDOWN and we're using slow
152   // get and put pixel routines
153
154   for(j=SourcePoint->y; j<SourcePoint->y+dy; j++)
155   {
156      for(i=SourcePoint->x; i<SourcePoint->x+dx; i++)
157      {
158         vgaPutPixel(i+alterx, j+altery, vgaGetPixel(i, j));
159      }
160   }
161
162   return TRUE;
163 }
164
165 BOOL STDCALL
166 VGADDI_BltBrush(SURFOBJ* Dest, XLATEOBJ* ColorTranslation, RECTL* DestRect,
167                 BRUSHOBJ* Brush, POINTL* BrushPoint, ROP4 Rop4)
168 {
169   UCHAR SolidColor;
170   ULONG Left;
171   ULONG Right;
172   ULONG Length;
173   PUCHAR Video;
174   UCHAR Mask;
175   ULONG i, j;
176
177   /* Punt brush blts to non-device surfaces. */
178   if (Dest->iType != STYPE_DEVICE)
179     {
180       return(FALSE);
181     }
182
183   /* Punt pattern fills. */
184   if (Rop4 == PATCOPY && Brush->iSolidColor == 0xFFFFFFFF)
185     {
186       return(FALSE);
187     }
188   if (Rop4 == PATCOPY)
189     {
190       SolidColor = Brush->iSolidColor;
191     }
192   else if (Rop4 == WHITENESS)
193     {
194       SolidColor = 1;
195     }
196   else
197     {
198       SolidColor = 0;
199     }
200
201   /* Fill any pixels on the left which don't fall into a full row of eight. */
202   if ((DestRect->left % 8) != 0)
203     {      
204       /* Disable writes to pixels outside of the destination rectangle. */
205       Mask = (1 << (8 - (DestRect->left % 8))) - 1;
206       if ((DestRect->right - DestRect->left) < (8 - (DestRect->left % 8)))
207         {
208           Mask &= ~((1 << (8 - (DestRect->right % 8))) - 1);
209         }
210       WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
211       WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask);
212
213       /* Write the same color to each pixel. */
214       Video = (PUCHAR)vidmem + DestRect->top * 80 + (DestRect->left >> 3);
215       for (i = DestRect->top; i < DestRect->bottom; i++, Video+=80)
216         {
217           (VOID)READ_REGISTER_UCHAR(Video);
218           WRITE_REGISTER_UCHAR(Video, SolidColor);
219         }
220     }
221
222   /* Enable writes to all pixels. */
223   WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
224   WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF);
225
226   /* Have we finished. */
227   if ((DestRect->right - DestRect->left) < (8 - (DestRect->left % 8)))
228     {
229       return(TRUE);
230     }
231
232   /* Fill any whole rows of eight pixels. */
233   Left = (DestRect->left + 7) & ~0x7;
234   Length = (DestRect->right >> 3) - (Left >> 3);  
235   for (i = DestRect->top; i < DestRect->bottom; i++)
236     {      
237       Video = (PUCHAR)vidmem + i * 80 + (Left >> 3);
238       for (j = 0; j < Length; j++, Video++)
239         {
240           WRITE_REGISTER_UCHAR(Video, SolidColor);
241         }
242     }
243
244   /* Fill any pixels on the right which don't fall into a complete row. */
245   if ((DestRect->right % 8) != 0)
246     {
247       /* Disable writes to pixels outside the destination rectangle. */
248       Mask = ~((1 << (8 - (DestRect->right % 8))) - 1);
249       WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
250       WRITE_PORT_UCHAR((PUCHAR)GRA_D, Mask);
251
252       Video = (PUCHAR)vidmem + DestRect->top * 80 + (DestRect->right >> 3);
253       for (i = DestRect->top; i < DestRect->bottom; i++, Video+=80)
254         {
255           /* Read the existing colours for this pixel into the latches. */
256           (VOID)READ_REGISTER_UCHAR(Video);
257           /* Write the new colour for the pixels selected in the mask. */
258           WRITE_REGISTER_UCHAR(Video, SolidColor);
259         }
260
261       /* Restore the default write masks. */
262       WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x8);
263       WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xFF);
264     }
265   return(TRUE);
266 }
267
268 BOOL STDCALL
269 VGADDI_BltSrc(SURFOBJ *Dest, SURFOBJ *Source, XLATEOBJ *ColorTranslation,
270               RECTL *DestRect, POINTL *SourcePoint)
271 {
272   RECT_ENUM RectEnum;
273   BOOL EnumMore;
274   PFN_VGABlt  BltOperation;
275   ULONG SourceType;
276   
277   SourceType = Source->iType;
278
279   if (SourceType == STYPE_BITMAP && Dest->iType == STYPE_DEVICE)
280     {
281       BltOperation = DIBtoVGA;
282     } 
283   else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_BITMAP)
284     {
285       BltOperation = VGAtoDIB;
286     } 
287   else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_DEVICE)
288     {
289       BltOperation = VGAtoVGA;
290     } 
291   else if (SourceType == STYPE_DEVBITMAP && Dest->iType == STYPE_DEVICE)
292     {
293       BltOperation = DFBtoVGA;
294     } 
295   else if (SourceType == STYPE_DEVICE && Dest->iType == STYPE_DEVBITMAP)
296     {
297       BltOperation = VGAtoDFB;
298     } 
299   else
300     {
301       /* Punt blts not involving a device or a device-bitmap. */
302       return(FALSE);
303    }
304
305   BltOperation(Dest, Source, ColorTranslation, DestRect, SourcePoint);
306   return(TRUE);
307 }
308
309 BOOL STDCALL
310 VGADDI_BltMask(SURFOBJ *Dest, SURFOBJ *Mask, XLATEOBJ *ColorTranslation,
311                RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush,
312                POINTL* BrushPoint)
313 {
314   LONG i, j, dx, dy, idxColor, RGBulong = 0, c8;
315   BYTE *initial, *tMask, *lMask;
316   
317   dx = DestRect->right  - DestRect->left;
318   dy = DestRect->bottom - DestRect->top;
319   
320   if (ColorTranslation == NULL)
321     {      
322       if (Mask != NULL)
323         {
324           tMask = Mask->pvBits;
325           for (j=0; j<dy; j++)
326             {
327               lMask = tMask;
328               c8 = 0;
329               for (i=0; i<dx; i++)
330                 {
331                   if((*lMask & maskbit[c8]) != 0)
332                     {
333                       vgaPutPixel(DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
334                     }
335                   c8++;
336                   if(c8 == 8) { lMask++; c8=0; }
337                 }
338               tMask += Mask->lDelta;
339             }
340         }
341     }
342 }
343
344 BOOL STDCALL
345 DrvBitBlt(SURFOBJ *Dest,
346           SURFOBJ *Source,
347           SURFOBJ *Mask,
348           CLIPOBJ *Clip,
349           XLATEOBJ *ColorTranslation,
350           RECTL *DestRect,
351           POINTL *SourcePoint,
352           POINTL *MaskPoint,
353           BRUSHOBJ *Brush,
354           POINTL *BrushPoint,
355           ROP4 rop4)
356 {
357   /* Punt bitblts with complex clipping to the GDI. */
358   if (Clip != NULL)
359     {
360       return(FALSE);
361     }
362   
363   switch (rop4)
364     {
365     case BLACKNESS:
366     case PATCOPY:
367     case WHITENESS:
368       return(VGADDI_BltBrush(Dest, ColorTranslation, DestRect, Brush,
369                              BrushPoint, rop4));
370
371     case SRCCOPY:
372       return(VGADDI_BltSrc(Dest, Source, ColorTranslation, DestRect, 
373                            SourcePoint));
374
375     case 0xAACC:
376       return(VGADDI_BltMask(Dest, Mask, ColorTranslation, DestRect,
377                             MaskPoint, Brush, BrushPoint));
378
379     default:
380       return(FALSE);
381     }
382 }