[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / reactos / subsystems / win32 / win32k / dib / dib32bpp.c
1 /*
2 * PROJECT: Win32 subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/dib/dib32bpp.c
5 * PURPOSE: Device Independant Bitmap functions, 32bpp
6 * PROGRAMMERS: Jason Filby
7 * Thomas Bluemel
8 * Gregor Anich
9 */
10
11 #include <win32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 VOID
17 DIB_32BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
18 {
19 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
20 PDWORD addr = (PDWORD)byteaddr + x;
21
22 *addr = c;
23 }
24
25 ULONG
26 DIB_32BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
27 {
28 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
29 PDWORD addr = (PDWORD)byteaddr + x;
30
31 return (ULONG)(*addr);
32 }
33
34 VOID
35 DIB_32BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
36 {
37 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
38 PDWORD addr = (PDWORD)byteaddr + x;
39 LONG lDelta = SurfObj->lDelta >> 2; // >> 2 == / sizeof(DWORD)
40
41 byteaddr = (PBYTE)addr;
42 while (y1++ < y2)
43 {
44 *addr = (DWORD)c;
45 addr += lDelta;
46 }
47 }
48
49 BOOLEAN
50 DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)
51 {
52 LONG i, j, sx, sy, xColor, f1;
53 PBYTE SourceBits, DestBits, SourceLine, DestLine;
54 PBYTE SourceBits_4BPP, SourceLine_4BPP;
55 PDWORD Source32, Dest32;
56
57 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
58 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta)
59 + 4 * BltInfo->DestRect.left;
60
61 switch (BltInfo->SourceSurface->iBitmapFormat)
62 {
63 case BMF_1BPP:
64
65 sx = BltInfo->SourcePoint.x;
66 sy = BltInfo->SourcePoint.y;
67
68 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
69 {
70 sx = BltInfo->SourcePoint.x;
71 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
72 {
73 if (DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
74 {
75 DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
76 } else {
77 DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
78 }
79 sx++;
80 }
81 sy++;
82 }
83 break;
84
85 case BMF_4BPP:
86 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0
87 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
88 + (BltInfo->SourcePoint.x >> 1);
89
90 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
91 {
92 SourceLine_4BPP = SourceBits_4BPP;
93 sx = BltInfo->SourcePoint.x;
94 f1 = sx & 1;
95
96 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
97 {
98 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
99 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
100 DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
101 if (f1 == 1) {
102 SourceLine_4BPP++;
103 f1 = 0;
104 } else {
105 f1 = 1;
106 }
107 sx++;
108 }
109
110 SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
111 }
112 break;
113
114 case BMF_8BPP:
115 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
116 DestLine = DestBits;
117
118 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
119 {
120 SourceBits = SourceLine;
121 DestBits = DestLine;
122
123 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
124 {
125 xColor = *SourceBits;
126 *((PDWORD) DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
127 SourceBits += 1;
128 DestBits += 4;
129 }
130
131 SourceLine += BltInfo->SourceSurface->lDelta;
132 DestLine += BltInfo->DestSurface->lDelta;
133 }
134 break;
135
136 case BMF_16BPP:
137 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
138 DestLine = DestBits;
139
140 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
141 {
142 SourceBits = SourceLine;
143 DestBits = DestLine;
144
145 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
146 {
147 xColor = *((PWORD) SourceBits);
148 *((PDWORD) DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
149 SourceBits += 2;
150 DestBits += 4;
151 }
152
153 SourceLine += BltInfo->SourceSurface->lDelta;
154 DestLine += BltInfo->DestSurface->lDelta;
155 }
156 break;
157
158 case BMF_24BPP:
159 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
160 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
161 + 3 * BltInfo->SourcePoint.x;
162 DestLine = DestBits;
163
164 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
165 {
166 SourceBits = SourceLine;
167 DestBits = DestLine;
168
169 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
170 {
171 xColor = (*(SourceBits + 2) << 0x10) +
172 (*(SourceBits + 1) << 0x08) +
173 (*(SourceBits));
174 *((PDWORD)DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
175 SourceBits += 3;
176 DestBits += 4;
177 }
178
179 SourceLine += BltInfo->SourceSurface->lDelta;
180 DestLine += BltInfo->DestSurface->lDelta;
181 }
182 break;
183
184 case BMF_32BPP:
185 if (NULL == BltInfo->XlateSourceToDest ||
186 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
187 {
188 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
189 {
190 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
191 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
192 {
193 RtlMoveMemory(DestBits, SourceBits, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
194 SourceBits += BltInfo->SourceSurface->lDelta;
195 DestBits += BltInfo->DestSurface->lDelta;
196 }
197 }
198 else
199 {
200 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
201 + ((BltInfo->SourcePoint.y
202 + BltInfo->DestRect.bottom
203 - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta)
204 + 4 * BltInfo->SourcePoint.x;
205 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 4 * BltInfo->DestRect.left;
206 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
207 {
208 RtlMoveMemory(DestBits, SourceBits, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
209 SourceBits -= BltInfo->SourceSurface->lDelta;
210 DestBits -= BltInfo->DestSurface->lDelta;
211 }
212 }
213 }
214 else
215 {
216 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
217 {
218 SourceBits = ((PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x);
219 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
220 {
221 if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
222 {
223 Dest32 = (DWORD *) DestBits;
224 Source32 = (DWORD *) SourceBits;
225 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
226 {
227 *Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
228 }
229 }
230 else
231 {
232 Dest32 = (DWORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
233 Source32 = (DWORD *) SourceBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
234 for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
235 {
236 *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
237 }
238 }
239 SourceBits += BltInfo->SourceSurface->lDelta;
240 DestBits += BltInfo->DestSurface->lDelta;
241 }
242 }
243 else
244 {
245 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
246 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 4 * BltInfo->DestRect.left;
247 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
248 {
249 if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
250 {
251 Dest32 = (DWORD *) DestBits;
252 Source32 = (DWORD *) SourceBits;
253 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
254 {
255 *Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
256 }
257 }
258 else
259 {
260 Dest32 = (DWORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
261 Source32 = (DWORD *) SourceBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
262 for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
263 {
264 *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
265 }
266 }
267 SourceBits -= BltInfo->SourceSurface->lDelta;
268 DestBits -= BltInfo->DestSurface->lDelta;
269 }
270 }
271 }
272 break;
273
274 default:
275 DPRINT1("DIB_32BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
276 return FALSE;
277 }
278
279 return TRUE;
280 }
281
282 BOOLEAN
283 DIB_32BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
284 RECTL* DestRect, RECTL *SourceRect,
285 XLATEOBJ *ColorTranslation, ULONG iTransColor)
286 {
287 ULONG X, Y, SourceX, SourceY = 0, Source = 0, wd;
288 ULONG *DestBits;
289
290 LONG DstHeight;
291 LONG DstWidth;
292 LONG SrcHeight;
293 LONG SrcWidth;
294
295 DstHeight = DestRect->bottom - DestRect->top;
296 DstWidth = DestRect->right - DestRect->left;
297 SrcHeight = SourceRect->bottom - SourceRect->top;
298 SrcWidth = SourceRect->right - SourceRect->left;
299
300 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
301 (DestRect->left << 2) +
302 DestRect->top * DestSurf->lDelta);
303 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 2);
304
305 for (Y = DestRect->top; Y < DestRect->bottom; Y++)
306 {
307 SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
308 for (X = DestRect->left; X < DestRect->right; X++, DestBits++)
309 {
310 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
311 if (SourceX >= 0 && SourceY >= 0 &&
312 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
313 {
314 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
315 if (Source != iTransColor)
316 {
317 *DestBits = XLATEOBJ_iXlate(ColorTranslation, Source);
318 }
319 }
320 }
321
322 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
323 }
324
325 return TRUE;
326 }
327
328 typedef union {
329 ULONG ul;
330 struct {
331 UCHAR red;
332 UCHAR green;
333 UCHAR blue;
334 UCHAR alpha;
335 } col;
336 } NICEPIXEL32;
337
338 static __inline UCHAR
339 Clamp8(ULONG val)
340 {
341 return (val > 255) ? 255 : val;
342 }
343
344 BOOLEAN
345 DIB_32BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
346 RECTL* SourceRect, CLIPOBJ* ClipRegion,
347 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
348 {
349 INT Rows, Cols, SrcX, SrcY;
350 register PULONG Dst;
351 BLENDFUNCTION BlendFunc;
352 register NICEPIXEL32 DstPixel, SrcPixel;
353 UCHAR Alpha, SrcBpp;
354
355 DPRINT("DIB_32BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
356 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
357 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
358
359 BlendFunc = BlendObj->BlendFunction;
360 if (BlendFunc.BlendOp != AC_SRC_OVER)
361 {
362 DPRINT1("BlendOp != AC_SRC_OVER\n");
363 return FALSE;
364 }
365 if (BlendFunc.BlendFlags != 0)
366 {
367 DPRINT1("BlendFlags != 0\n");
368 return FALSE;
369 }
370 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
371 {
372 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
373 return FALSE;
374 }
375 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
376 BitsPerFormat(Source->iBitmapFormat) != 32)
377 {
378 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
379 return FALSE;
380 }
381
382 Dst = (PULONG)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
383 (DestRect->left << 2));
384 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
385
386 Rows = 0;
387 SrcY = SourceRect->top;
388 while (++Rows <= DestRect->bottom - DestRect->top)
389 {
390 Cols = 0;
391 SrcX = SourceRect->left;
392 while (++Cols <= DestRect->right - DestRect->left)
393 {
394 SrcPixel.ul = DIB_GetSource(Source, SrcX, SrcY, ColorTranslation);
395 SrcPixel.col.red = (SrcPixel.col.red * BlendFunc.SourceConstantAlpha) / 255;
396 SrcPixel.col.green = (SrcPixel.col.green * BlendFunc.SourceConstantAlpha) / 255;
397 SrcPixel.col.blue = (SrcPixel.col.blue * BlendFunc.SourceConstantAlpha) / 255;
398 SrcPixel.col.alpha = (32 == SrcBpp) ?
399 (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
400 BlendFunc.SourceConstantAlpha ;
401
402 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
403 SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha ;
404
405 DstPixel.ul = *Dst;
406 DstPixel.col.red = Clamp8((DstPixel.col.red * (255 - Alpha)) / 255 + SrcPixel.col.red) ;
407 DstPixel.col.green = Clamp8((DstPixel.col.green * (255 - Alpha)) / 255 + SrcPixel.col.green) ;
408 DstPixel.col.blue = Clamp8((DstPixel.col.blue * (255 - Alpha)) / 255 + SrcPixel.col.blue) ;
409 DstPixel.col.alpha = Clamp8((DstPixel.col.alpha * (255 - Alpha)) / 255 + SrcPixel.col.alpha) ;
410 *Dst++ = DstPixel.ul;
411 SrcX = SourceRect->left + (Cols*(SourceRect->right - SourceRect->left))/(DestRect->right - DestRect->left);
412 }
413 Dst = (PULONG)((ULONG_PTR)Dest->pvScan0 + ((DestRect->top + Rows) * Dest->lDelta) +
414 (DestRect->left << 2));
415 SrcY = SourceRect->top + (Rows*(SourceRect->bottom - SourceRect->top))/(DestRect->bottom - DestRect->top);
416 }
417
418 return TRUE;
419 }
420
421 /* EOF */