Reverted latest changes.
[reactos.git] / reactos / subsys / win32k / eng / bitblt.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI BitBlt Functions
5 * FILE: subsys/win32k/eng/bitblt.c
6 * PROGRAMER: Jason Filby
7 * REVISION HISTORY:
8 * 2/10/1999: Created
9 */
10
11 #include <ddk/winddi.h>
12 #include <ddk/ntddk.h>
13 #include <ntos/minmax.h>
14 #include "brush.h"
15 #include "clip.h"
16 #include "objects.h"
17 #include <include/mouse.h>
18 #include <include/object.h>
19 #include <include/dib.h>
20 #include <include/surface.h>
21 #include <include/copybits.h>
22
23 BOOL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
24 {
25 static const RECTL rclEmpty = { 0, 0, 0, 0 };
26
27 prcDst->left = max(prcSrc1->left, prcSrc2->left);
28 prcDst->right = min(prcSrc1->right, prcSrc2->right);
29
30 if (prcDst->left < prcDst->right)
31 {
32 prcDst->top = max(prcSrc1->top, prcSrc2->top);
33 prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
34
35 if (prcDst->top < prcDst->bottom) return(TRUE);
36 }
37
38 *prcDst = rclEmpty;
39
40 return(FALSE);
41 }
42
43 INT abs(INT nm);
44
45 BOOL STDCALL
46 EngBitBlt(SURFOBJ *Dest,
47 SURFOBJ *Source,
48 SURFOBJ *Mask,
49 CLIPOBJ *ClipRegion,
50 XLATEOBJ *ColorTranslation,
51 RECTL *DestRect,
52 POINTL *SourcePoint,
53 POINTL *MaskRect,
54 BRUSHOBJ *Brush,
55 POINTL *BrushOrigin,
56 ROP4 rop4)
57 {
58 BOOLEAN ret;
59 BYTE clippingType;
60 RECTL rclTmp;
61 POINTL ptlTmp;
62 RECT_ENUM RectEnum;
63 BOOL EnumMore;
64 PSURFGDI DestGDI, SourceGDI;
65 HSURF hTemp;
66 PSURFOBJ TempSurf = NULL;
67 BOOLEAN canCopyBits;
68 POINTL TempPoint;
69 RECTL TempRect;
70 SIZEL TempSize;
71
72 if(Source != NULL) SourceGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Source);
73 if(Dest != NULL) DestGDI = (PSURFGDI)AccessInternalObjectFromUserObject(Dest);
74
75 if (Source != NULL)
76 {
77 MouseSafetyOnDrawStart(Source, SourceGDI, SourcePoint->x, SourcePoint->y,
78 (SourcePoint->x + abs(DestRect->right - DestRect->left)),
79 (SourcePoint->y + abs(DestRect->bottom - DestRect->top)));
80 }
81 MouseSafetyOnDrawStart(Dest, DestGDI, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
82
83 // If we don't have to do anything special, we can punt to DrvCopyBits
84 // if it exists
85 if( (Mask == NULL) && (MaskRect == NULL) && (Brush == NULL) &&
86 (BrushOrigin == NULL) && (rop4 == 0) )
87 {
88 canCopyBits = TRUE;
89 } else
90 canCopyBits = FALSE;
91
92 // Check for CopyBits or BitBlt hooks if one is not a GDI managed bitmap, IF:
93 // * The destination bitmap is not managed by the GDI OR
94 if(Dest->iType != STYPE_BITMAP)
95 {
96 // Destination surface is device managed
97 if (DestGDI->BitBlt!=NULL)
98 {
99 if (Source!=NULL)
100 {
101 // Get the source into a format compatible surface
102 TempPoint.x = 0;
103 TempPoint.y = 0;
104 TempRect.top = 0;
105 TempRect.left = 0;
106 TempRect.bottom = DestRect->bottom - DestRect->top;
107 TempRect.right = DestRect->right - DestRect->left;
108 TempSize.cx = TempRect.right;
109 TempSize.cy = TempRect.bottom;
110
111 hTemp = EngCreateBitmap(TempSize,
112 DIB_GetDIBWidthBytes(DestRect->right - DestRect->left, BitsPerFormat(Dest->iBitmapFormat)),
113 Dest->iBitmapFormat, 0, NULL);
114 TempSurf = (PSURFOBJ)AccessUserObject((ULONG)hTemp);
115
116 // FIXME: Skip creating a TempSurf if we have the same BPP and palette
117 EngBitBlt(TempSurf, Source, NULL, NULL, ColorTranslation, &TempRect, SourcePoint, NULL, NULL, NULL, 0);
118 }
119
120 ret = DestGDI->BitBlt(Dest, TempSurf, Mask, ClipRegion,
121 NULL, DestRect, &TempPoint,
122 MaskRect, Brush, BrushOrigin, rop4);
123
124 MouseSafetyOnDrawEnd(Source, SourceGDI);
125 MouseSafetyOnDrawEnd(Dest, DestGDI);
126
127 return ret;
128 }
129 }
130
131 // * The source bitmap is not managed by the GDI and we didn't already obtain it using EngCopyBits from the device
132 if(Source->iType != STYPE_BITMAP && SourceGDI->CopyBits == NULL)
133 {
134 if (SourceGDI->BitBlt!=NULL)
135 {
136 // Request the device driver to return the bitmap in a format compatible with the device
137 ret = SourceGDI->BitBlt(Dest, Source, Mask, ClipRegion,
138 NULL, DestRect, SourcePoint,
139 MaskRect, Brush, BrushOrigin, rop4);
140
141 MouseSafetyOnDrawEnd(Source, SourceGDI);
142 MouseSafetyOnDrawEnd(Dest, DestGDI);
143
144 return ret;
145
146 // Convert the surface from the driver into the required destination surface
147 }
148 }
149
150 // Determine clipping type
151 if (ClipRegion == (CLIPOBJ *) NULL)
152 {
153 clippingType = DC_TRIVIAL;
154 } else {
155 clippingType = ClipRegion->iDComplexity;
156 }
157
158 // We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE]
159 switch(clippingType)
160 {
161 case DC_TRIVIAL:
162 CopyBitsCopy(Dest, Source, DestGDI, SourceGDI, DestRect, SourcePoint, Source->lDelta, ColorTranslation);
163
164 MouseSafetyOnDrawEnd(Source, SourceGDI);
165 MouseSafetyOnDrawEnd(Dest, DestGDI);
166
167 return(TRUE);
168
169 case DC_RECT:
170
171 // Clip the blt to the clip rectangle
172 EngIntersectRect(&rclTmp, DestRect, &ClipRegion->rclBounds);
173
174 ptlTmp.x = SourcePoint->x + rclTmp.left - DestRect->left;
175 ptlTmp.y = SourcePoint->y + rclTmp.top - DestRect->top;
176
177 MouseSafetyOnDrawEnd(Source, SourceGDI);
178 MouseSafetyOnDrawEnd(Dest, DestGDI);
179
180 return(TRUE);
181
182 case DC_COMPLEX:
183
184 CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
185
186 do {
187 EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
188
189 if (RectEnum.c > 0)
190 {
191 RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
192 RECTL* prcl = &RectEnum.arcl[0];
193
194 do {
195 EngIntersectRect(prcl, prcl, DestRect);
196
197 ptlTmp.x = SourcePoint->x + prcl->left - DestRect->left;
198 ptlTmp.y = SourcePoint->y + prcl->top - DestRect->top;
199
200 prcl++;
201
202 } while (prcl < prclEnd);
203 }
204
205 } while(EnumMore);
206
207 MouseSafetyOnDrawEnd(Source, SourceGDI);
208 MouseSafetyOnDrawEnd(Dest, DestGDI);
209
210 return(TRUE);
211 }
212
213 MouseSafetyOnDrawEnd(Source, SourceGDI);
214 MouseSafetyOnDrawEnd(Dest, DestGDI);
215
216 return(FALSE);
217 }