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