1 /*
2 * PROJECT: Win32 subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: win32ss/gdi/dib/dib32bpp.c
5 * PURPOSE: Device Independant Bitmap functions, 32bpp
6 * PROGRAMMERS: Jason Filby
7 * Thomas Bluemel
8 * Gregor Anich
9 * Doug Lyons
10 */
11
12 #include <win32k.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 #define DEC_OR_INC(var, decTrue, amount) \
18 ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
19
20 VOID
DIB_32BPP_PutPixel(SURFOBJ * SurfObj,LONG x,LONG y,ULONG c)21 DIB_32BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
22 {
23 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
24 PDWORD addr = (PDWORD)byteaddr + x;
25
26 *addr = c;
27 }
28
29 ULONG
DIB_32BPP_GetPixel(SURFOBJ * SurfObj,LONG x,LONG y)30 DIB_32BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
31 {
32 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
33 PDWORD addr = (PDWORD)byteaddr + x;
34
35 return (ULONG)(*addr);
36 }
37
38 VOID
DIB_32BPP_VLine(SURFOBJ * SurfObj,LONG x,LONG y1,LONG y2,ULONG c)39 DIB_32BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
40 {
41 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
42 PDWORD addr = (PDWORD)byteaddr + x;
43 LONG lDelta = SurfObj->lDelta >> 2; // >> 2 == / sizeof(DWORD)
44
45 byteaddr = (PBYTE)addr;
46 while (y1++ < y2)
47 {
48 *addr = (DWORD)c;
49 addr += lDelta;
50 }
51 }
52
53 BOOLEAN
DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)54 DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)
55 {
56 LONG i, j, sx, sy, xColor, f1;
57 PBYTE SourceBits, DestBits, SourceLine, DestLine;
58 PBYTE SourceBitsT, SourceBitsB, DestBitsT, DestBitsB;
59 PBYTE SourceBits_4BPP, SourceLine_4BPP;
60 PDWORD Source32, Dest32;
61 DWORD Index;
62 LONG DestWidth, DestHeight;
63 BOOLEAN bTopToBottom, bLeftToRight;
64 BOOLEAN blDeltaSrcNeg, blDeltaDestNeg;
65 BOOLEAN blDeltaAdjustDone = FALSE;
66
67 DPRINT("DIB_32BPP_BitBltSrcCopy: SourcePoint (%d, %d), SourceSurface cx/cy (%d/%d), "
68 "DestSurface cx/cy (%d/%d) DestRect: (%d,%d)-(%d,%d)\n",
69 BltInfo->SourcePoint.x, BltInfo->SourcePoint.y,
70 BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
71 BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
72 BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
73
74 DPRINT("BltInfo->DestSurface->lDelta is '%d' and BltInfo->SourceSurface->lDelta is '%d'.\n",
75 BltInfo->DestSurface->lDelta, BltInfo->SourceSurface->lDelta);
76
77 DPRINT("iBitmapFormat is %d and width,height is (%d,%d).\n", BltInfo->SourceSurface->iBitmapFormat,
78 BltInfo->DestRect.right - BltInfo->DestRect.left, BltInfo->DestRect.bottom - BltInfo->DestRect.top);
79
80 DPRINT("BltInfo->SourcePoint.x is '%d' and BltInfo->SourcePoint.y is '%d'.\n",
81 BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
82
83 /* Do not deal with negative numbers for these values */
84 if ((BltInfo->DestRect.left < 0) || (BltInfo->DestRect.top < 0) ||
85 (BltInfo->DestRect.right < 0) || (BltInfo->DestRect.bottom < 0))
86 return FALSE;
87
88 /* Detect negative lDelta's meaning Bottom-Up bitmaps */
89 blDeltaSrcNeg = BltInfo->SourceSurface->lDelta < 0;
90 blDeltaDestNeg = BltInfo->DestSurface->lDelta < 0;
91
92 /* Get back left to right flip here */
93 bLeftToRight = BltInfo->DestRect.left > BltInfo->DestRect.right;
94
95 /* Check for top to bottom flip needed. */
96 bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
97
98 DPRINT("bTopToBottom is '%d' and DestSurface->lDelta < 0 is '%d' and SourceSurface->lDelta < 0 is '%d'.\n",
99 bTopToBottom, BltInfo->DestSurface->lDelta < 0 ? 1 : 0, BltInfo->SourceSurface->lDelta < 0 ? 1 : 0);
100
101 /* Make WellOrdered with top < bottom and left < right */
102 RECTL_vMakeWellOrdered(&BltInfo->DestRect);
103
104 DestWidth = BltInfo->DestRect.right - BltInfo->DestRect.left;
105 DestHeight = BltInfo->DestRect.bottom - BltInfo->DestRect.top;
106
107 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
108 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta)
109 + 4 * BltInfo->DestRect.left;
110
111 DPRINT("iBitmapFormat is %d and width,height is (%d,%d).\n", BltInfo->SourceSurface->iBitmapFormat,
112 DestWidth, DestHeight);
113
114 switch (BltInfo->SourceSurface->iBitmapFormat)
115 {
116 case BMF_1BPP:
117 DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
118 DestWidth);
119
120 if (bLeftToRight || bTopToBottom)
121 DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
122
123 sx = BltInfo->SourcePoint.x;
124
125 /* This sets sy to the top line */
126 sy = BltInfo->SourcePoint.y;
127
128 if (bTopToBottom)
129 {
130 /* This sets sy to the bottom line */
131 sy += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
132 }
133
134 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
135 {
136 sx = BltInfo->SourcePoint.x;
137
138 if (bLeftToRight)
139 {
140 /* This sets the sx to the rightmost pixel */
141 sx += (DestWidth - 1);
142 }
143
144 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
145 {
146 if (DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
147 {
148 DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
149 }
150 else
151 {
152 DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
153 }
154
155 DEC_OR_INC(sx, bLeftToRight, 1);
156 }
157 DEC_OR_INC(sy, bTopToBottom, 1);
158 }
159 break;
160
161 case BMF_4BPP:
162 DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
163 DestWidth);
164
165 if (bLeftToRight || bTopToBottom)
166 DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
167
168 /* This sets SourceBits_4BPP to the top line */
169 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0
170 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
171 + (BltInfo->SourcePoint.x >> 1);
172
173 if (bTopToBottom)
174 {
175 /* This sets SourceBits_4BPP to the bottom line */
176 SourceBits_4BPP += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
177 }
178
179 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
180 {
181 SourceLine_4BPP = SourceBits_4BPP;
182 sx = BltInfo->SourcePoint.x;
183
184 if (bLeftToRight)
185 {
186 /* This sets sx to the rightmost pixel */
187 sx += (DestWidth - 1);
188 }
189
190 f1 = sx & 1;
191
192 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
193 {
194 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
195 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
196 DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
197 if (f1 == 1) {
198 DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
199 f1 = 0;
200 } else {
201 f1 = 1;
202 }
203 DEC_OR_INC(sx, bLeftToRight, 1);
204 }
205 DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
206 }
207 break;
208
209 case BMF_8BPP:
210 DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n",
211 DestWidth);
212
213 if (bLeftToRight || bTopToBottom)
214 DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
215
216 /* This sets SourceLine to the top line */
217 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
218 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
219 + BltInfo->SourcePoint.x;
220 DestLine = DestBits;
221
222 if (bTopToBottom)
223 {
224 /* This sets SourceLine to the bottom line */
225 SourceLine += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
226 }
227
228 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
229 {
230 SourceBits = SourceLine;
231 DestBits = DestLine;
232
233 if (bLeftToRight)
234 {
235 /* This sets the SourceBits to the rightmost pixel */
236 SourceBits += (DestWidth - 1);
237 }
238
239 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
240 {
241 xColor = *SourceBits;
242 *((PDWORD) DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
243 DEC_OR_INC(SourceBits, bLeftToRight, 1);
244 DestBits += 4;
245 }
246 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
247 DestLine += BltInfo->DestSurface->lDelta;
248 }
249 break;
250
251 case BMF_16BPP:
252 DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
253 DestWidth);
254
255 if (bLeftToRight || bTopToBottom)
256 DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
257
258 /* This sets SourceLine to the top line */
259 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
260 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
261 + 2 * BltInfo->SourcePoint.x;
262 DestLine = DestBits;
263
264 if (bTopToBottom)
265 {
266 /* This sets SourceLine to the bottom line */
267 SourceLine += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
268 }
269
270 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
271 {
272 SourceBits = SourceLine;
273 DestBits = DestLine;
274
275 if (bLeftToRight)
276 {
277 /* This sets the SourceBits to the rightmost pixel */
278 SourceBits += (DestWidth - 1) * 2;
279 }
280
281 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
282 {
283 xColor = *((PWORD) SourceBits);
284 *((PDWORD) DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
285 DEC_OR_INC(SourceBits, bLeftToRight, 2);
286 DestBits += 4;
287 }
288
289 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
290 DestLine += BltInfo->DestSurface->lDelta;
291 }
292 break;
293
294 case BMF_24BPP:
295 DPRINT("24BPP Case Selected with DestRect Width of '%d'.\n",
296 DestWidth);
297
298 if (bLeftToRight || bTopToBottom)
299 DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
300
301 /* This sets SourceLine to the top line */
302 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
303 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
304 + 3 * BltInfo->SourcePoint.x;
305
306 if (bTopToBottom)
307 {
308 /* This sets SourceLine to the bottom line */
309 SourceLine += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
310 }
311
312 DestLine = DestBits;
313
314 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
315 {
316 SourceBits = SourceLine;
317 DestBits = DestLine;
318
319 if (bLeftToRight)
320 {
321 /* This sets the SourceBits to the rightmost pixel */
322 SourceBits += (DestWidth - 1) * 3;
323 }
324
325 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
326 {
327 xColor = (*(SourceBits + 2) << 0x10) +
328 (*(SourceBits + 1) << 0x08) +
329 (*(SourceBits));
330 *((PDWORD)DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
331 DEC_OR_INC(SourceBits, bLeftToRight, 3);
332 DestBits += 4;
333 }
334
335 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
336 DestLine += BltInfo->DestSurface->lDelta;
337 }
338 break;
339
340 case BMF_32BPP:
341 DPRINT("32BPP Case Selected with SourcePoint (%d,%d) and DestRect Width/height of '%d/%d' DestRect: (%d,%d)-(%d,%d).\n",
342 BltInfo->SourcePoint.x, BltInfo->SourcePoint.y, DestWidth, DestHeight,
343 BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
344
345 if (bLeftToRight || bTopToBottom)
346 DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
347
348 /* This handles the negative lDelta's which represent Top-to-Bottom bitmaps */
349 if (((blDeltaSrcNeg || blDeltaDestNeg) && !(blDeltaSrcNeg && blDeltaDestNeg)) && bTopToBottom)
350 {
351 DPRINT("Adjusting for lDelta's here.\n");
352 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
353 {
354 /* SourceBits points to top-left pixel for lDelta < 0 and bottom-left for lDelta > 0 */
355 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
356 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
357 + 4 * BltInfo->SourcePoint.x;
358 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
359 {
360 RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
361 SourceBits += BltInfo->SourceSurface->lDelta;
362 DestBits += BltInfo->DestSurface->lDelta;
363 }
364 }
365 else
366 {
367 /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
368 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
369 + ((BltInfo->SourcePoint.y + DestHeight - 1) * BltInfo->SourceSurface->lDelta)
370 + 4 * BltInfo->SourcePoint.x;
371 /* DestBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
372 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
373 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
374 + 4 * BltInfo->DestRect.left;
375 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
376 {
377 RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
378 SourceBits -= BltInfo->SourceSurface->lDelta;
379 DestBits -= BltInfo->DestSurface->lDelta;
380 }
381 }
382 blDeltaAdjustDone = TRUE;
383 }
384
385 /* This tests for whether we can use simplified/quicker code below.
386 * It works for increasing source and destination areas only and there is no overlap and no flip.
387 */
388 if ((BltInfo->XlateSourceToDest == NULL ||
389 (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
390 (!bTopToBottom && !bLeftToRight))
391 {
392 DPRINT("XO_TRIVIAL is TRUE.\n");
393
394 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
395 {
396 /* SourceBits points to top-left pixel for lDelta < 0 and bottom-left for lDelta > 0 */
397 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
398 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
399 + 4 * BltInfo->SourcePoint.x;
400 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
401 {
402 RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
403 SourceBits += BltInfo->SourceSurface->lDelta;
404 DestBits += BltInfo->DestSurface->lDelta;
405 }
406 }
407 else
408 {
409 /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
410 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
411 + ((BltInfo->SourcePoint.y
412 + DestHeight - 1) * BltInfo->SourceSurface->lDelta)
413 + 4 * BltInfo->SourcePoint.x;
414 /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
415 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
416 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
417 + 4 * BltInfo->DestRect.left;
418 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
419 {
420 RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
421 SourceBits -= BltInfo->SourceSurface->lDelta;
422 DestBits -= BltInfo->DestSurface->lDelta;
423 }
424 }
425 }
426 else
427 {
428 DPRINT("XO_TRIVIAL is NOT TRUE.\n");
429
430 if (!bTopToBottom && !bLeftToRight)
431 {
432 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
433 {
434 SourceBits = ((PBYTE)BltInfo->SourceSurface->pvScan0
435 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
436 + 4 * BltInfo->SourcePoint.x);
437 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
438 {
439 if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
440 {
441 Dest32 = (DWORD *) DestBits;
442 Source32 = (DWORD *) SourceBits;
443 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
444 {
445 *Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
446 }
447 }
448 else
449 {
450 Dest32 = (DWORD *) DestBits + (DestWidth - 1);
451 Source32 = (DWORD *) SourceBits + (DestWidth - 1);
452 for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
453 {
454 *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
455 }
456 }
457 SourceBits += BltInfo->SourceSurface->lDelta;
458 DestBits += BltInfo->DestSurface->lDelta;
459 }
460 }
461 else
462 {
463 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
464 + ((BltInfo->SourcePoint.y
465 + DestHeight - 1) * BltInfo->SourceSurface->lDelta)
466 + 4 * BltInfo->SourcePoint.x;
467 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
468 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
469 + 4 * BltInfo->DestRect.left;
470 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
471 {
472 if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
473 {
474 Dest32 = (DWORD *) DestBits;
475 Source32 = (DWORD *) SourceBits;
476 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
477 {
478 *Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
479 }
480 }
481 else
482 {
483 Dest32 = (DWORD *) DestBits + (DestWidth - 1);
484 Source32 = (DWORD *) SourceBits + (DestWidth - 1);
485 for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
486 {
487 *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
488 }
489 }
490 SourceBits -= BltInfo->SourceSurface->lDelta;
491 DestBits -= BltInfo->DestSurface->lDelta;
492 }
493 }
494 }
495 else
496 {
497 /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
498 BOOL TopToBottomDone = FALSE;
499
500 /* No need to flip a LeftToRight bitmap only one pixel wide */
501 if ((bLeftToRight) && (DestWidth > 1))
502 {
503 DPRINT("Flip is bLeftToRight.\n");
504
505 /* Allocate enough pixels for a row in DWORD's */
506 DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
507 (DestWidth + 1) * 4, TAG_DIB);
508 if (store == NULL)
509 {
510 DPRINT1("Storage Allocation Failed.\n");
511 return FALSE;
512 }
513
514 /* This sets SourceBits to the bottom line */
515 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
516 + ((BltInfo->SourcePoint.y + DestHeight - 1)
517 * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
518
519 /* This sets DestBits to the bottom line */
520 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
521 + (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta
522 + 4 * BltInfo->DestRect.left;
523
524 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
525 {
526
527 /* Set Dest32 to right pixel */
528 Dest32 = (DWORD *) DestBits + (DestWidth - 1);
529 Source32 = (DWORD *) SourceBits;
530
531 Index = 0;
532
533 /* Store pixels from left to right */
534 for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
535 {
536 store[Index] = *Source32++;
537 Index++;
538 }
539
540 Index = 0;
541
542 /* Copy stored dat to pixels from right to left */
543 for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
544 {
545 *Dest32-- = store[Index];
546 Index++;
547 }
548 SourceBits -= BltInfo->SourceSurface->lDelta;
549 DestBits -= BltInfo->DestSurface->lDelta;
550 }
551 ExFreePoolWithTag(store, TAG_DIB);
552 TopToBottomDone = TRUE;
553 }
554
555 /* Top to Botoom Handling if bitmap more than one pixel high */
556 if ((bTopToBottom) && (DestHeight > 1))
557 {
558 /* Note: It is very important that this code remain optimized for time used.
559 * Otherwise you will have random crashes in ReactOS that are undesirable.
560 * For an example of this just try executing the code here two times.
561 */
562
563 DPRINT("Flip is bTopToBottom.\n");
564
565 /* Allocate enough pixels for a row in DWORD's */
566 DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
567 (DestWidth + 1) * 4, TAG_DIB);
568 if (store == NULL)
569 {
570 DPRINT1("Storage Allocation Failed.\n");
571 return FALSE;
572 }
573
574 /* This set DestBitsT to the top line */
575 DestBitsT = (PBYTE)BltInfo->DestSurface->pvScan0
576 + ((BltInfo->DestRect.top) * BltInfo->DestSurface->lDelta)
577 + 4 * BltInfo->DestRect.left;
578
579 /* This sets DestBitsB to the bottom line */
580 DestBitsB = (PBYTE)BltInfo->DestSurface->pvScan0
581 + (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta
582 + 4 * BltInfo->DestRect.left;
583
584 /* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
585 * and have already completed the bLeftToRight. So we will lose our first flip output
586 * unless we work with its output which is at the destination site. So in this case
587 * our new Source becomes the previous outputs Destination.
588 * Also in we use the same logic when we have corrected for negative lDelta's above
589 * and already completed a flip from Source to Destination for the first step
590 */
591
592 if (TopToBottomDone || blDeltaAdjustDone)
593 {
594 /* This sets SourceBitsB to the bottom line */
595 SourceBitsB = DestBitsB;
596
597 /* This sets SourceBitsT to the top line */
598 SourceBitsT = DestBitsT;
599 }
600 else
601 {
602 /* This sets SourceBitsB to the bottom line */
603 SourceBitsB = (PBYTE)BltInfo->SourceSurface->pvScan0
604 + ((BltInfo->SourcePoint.y + DestHeight - 1)
605 * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
606
607 /* This sets SourceBitsT to the top line */
608 SourceBitsT = (PBYTE)BltInfo->SourceSurface->pvScan0
609 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
610 }
611
612 /* Overlaps and Vertical flips do not mix well. So we test for this and handle it
613 * by using two operations. First we just do a copy of the source to the destination.
614 * Then we do a flip in place at the destination location and we are done.
615 */
616 if ((BltInfo->SourcePoint.y != BltInfo->DestRect.top) && // The values are not equal and
617 (abs(BltInfo->SourcePoint.y - BltInfo->DestRect.top) < (DestHeight + 2)) && // they are NOT separated by > DestHeight
618 (BltInfo->SourceSurface->pvScan0 == BltInfo->DestSurface->pvScan0)) // and same surface (probably screen)
619 {
620 DPRINT("Flips Need Adjustments, so do move here.\n");
621
622 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
623 {
624 /* SourceBits points to top-left pixel for lDelta < 0 and bottom-left for lDelta > 0 */
625 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
626 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
627 + 4 * BltInfo->SourcePoint.x;
628 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
629 {
630 RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
631 SourceBits += BltInfo->SourceSurface->lDelta;
632 DestBits += BltInfo->DestSurface->lDelta;
633 }
634 }
635 else
636 {
637 /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
638 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
639 + ((BltInfo->SourcePoint.y
640 + DestHeight - 1) * BltInfo->SourceSurface->lDelta)
641 + 4 * BltInfo->SourcePoint.x;
642 /* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
643 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
644 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
645 + 4 * BltInfo->DestRect.left;
646 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
647 {
648 RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
649 SourceBits -= BltInfo->SourceSurface->lDelta;
650 DestBits -= BltInfo->DestSurface->lDelta;
651 }
652 }
653
654 /* This sets SourceBitsB to the bottom line */
655 SourceBitsB = DestBitsB;
656
657 /* This sets SourceBitsT to the top line */
658 SourceBitsT = DestBitsT;
659 }
660
661 /* Vertical Flip code starts here */
662 for (j = 0; j < DestHeight / 2 ; j++)
663 {
664 /* Store bottom row of Source pixels */
665 RtlMoveMemory(store, SourceBitsB, 4 * DestWidth);
666
667 /* Copy top Source row to bottom Destination row overwriting it */
668 RtlMoveMemory(DestBitsB, SourceBitsT, 4 * DestWidth);
669
670 /* Copy stored bottom row of Source pixels to Destination top row of pixels */
671 RtlMoveMemory(DestBitsT, store, 4 * DestWidth);
672
673 /* Index top rows down and bottom rows up */
674 SourceBitsT += BltInfo->SourceSurface->lDelta;
675 SourceBitsB -= BltInfo->SourceSurface->lDelta;
676
677 DestBitsT += BltInfo->DestSurface->lDelta;
678 DestBitsB -= BltInfo->DestSurface->lDelta;
679 }
680 if (DestHeight % 2)
681 {
682 /* If we had an odd number of lines we handle the center one here */
683 DPRINT("Handling Top To Bottom with Odd Number of lines.\n");
684 RtlMoveMemory(DestBitsB, SourceBitsT, 4 * DestWidth);
685 }
686 ExFreePoolWithTag(store, TAG_DIB);
687 }
688 }
689 }
690 break;
691
692 default:
693 DPRINT1("DIB_32BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
694 return FALSE;
695 }
696
697 return TRUE;
698 }
699
700 BOOLEAN
DIB_32BPP_TransparentBlt(SURFOBJ * DestSurf,SURFOBJ * SourceSurf,RECTL * DestRect,RECTL * SourceRect,XLATEOBJ * ColorTranslation,ULONG iTransColor)701 DIB_32BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
702 RECTL* DestRect, RECTL *SourceRect,
703 XLATEOBJ *ColorTranslation, ULONG iTransColor)
704 {
705 LONG X, Y, SourceX, SourceY = 0, wd;
706 ULONG *DestBits, Source = 0;
707
708 LONG DstHeight;
709 LONG DstWidth;
710 LONG SrcHeight;
711 LONG SrcWidth;
712
713 DstHeight = DestRect->bottom - DestRect->top;
714 DstWidth = DestRect->right - DestRect->left;
715 SrcHeight = SourceRect->bottom - SourceRect->top;
716 SrcWidth = SourceRect->right - SourceRect->left;
717
718 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
719 (DestRect->left << 2) +
720 DestRect->top * DestSurf->lDelta);
721 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 2);
722
723 for (Y = DestRect->top; Y < DestRect->bottom; Y++)
724 {
725 SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
726 for (X = DestRect->left; X < DestRect->right; X++, DestBits++)
727 {
728 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
729 if (SourceX >= 0 && SourceY >= 0 &&
730 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
731 {
732 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
733 if ((0x00FFFFFF & Source) != (0x00FFFFFF & iTransColor))
734 {
735 *DestBits = XLATEOBJ_iXlate(ColorTranslation, Source);
736 }
737 }
738 }
739
740 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
741 }
742
743 return TRUE;
744 }
745
746 typedef union {
747 ULONG ul;
748 struct {
749 UCHAR red;
750 UCHAR green;
751 UCHAR blue;
752 UCHAR alpha;
753 } col;
754 } NICEPIXEL32;
755
756 static __inline UCHAR
Clamp8(ULONG val)757 Clamp8(ULONG val)
758 {
759 return (val > 255) ? 255 : (UCHAR)val;
760 }
761
762 BOOLEAN
DIB_32BPP_AlphaBlend(SURFOBJ * Dest,SURFOBJ * Source,RECTL * DestRect,RECTL * SourceRect,CLIPOBJ * ClipRegion,XLATEOBJ * ColorTranslation,BLENDOBJ * BlendObj)763 DIB_32BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
764 RECTL* SourceRect, CLIPOBJ* ClipRegion,
765 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
766 {
767 INT Rows, Cols, SrcX, SrcY;
768 register PULONG Dst;
769 BLENDFUNCTION BlendFunc;
770 register NICEPIXEL32 DstPixel, SrcPixel;
771 UCHAR Alpha, SrcBpp;
772
773 DPRINT("DIB_32BPP_AlphaBlend: SourceRect: (%d,%d)-(%d,%d), DestRect: (%d,%d)-(%d,%d)\n",
774 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
775 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
776
777 BlendFunc = BlendObj->BlendFunction;
778 if (BlendFunc.BlendOp != AC_SRC_OVER)
779 {
780 DPRINT1("BlendOp != AC_SRC_OVER\n");
781 return FALSE;
782 }
783 if (BlendFunc.BlendFlags != 0)
784 {
785 DPRINT1("BlendFlags != 0\n");
786 return FALSE;
787 }
788 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
789 {
790 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
791 return FALSE;
792 }
793 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
794 BitsPerFormat(Source->iBitmapFormat) != 32)
795 {
796 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
797 return FALSE;
798 }
799
800 Dst = (PULONG)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
801 (DestRect->left << 2));
802 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
803
804 Rows = 0;
805 SrcY = SourceRect->top;
806 while (++Rows <= DestRect->bottom - DestRect->top)
807 {
808 Cols = 0;
809 SrcX = SourceRect->left;
810 while (++Cols <= DestRect->right - DestRect->left)
811 {
812 SrcPixel.ul = DIB_GetSource(Source, SrcX, SrcY, ColorTranslation);
813 SrcPixel.col.red = (SrcPixel.col.red * BlendFunc.SourceConstantAlpha) / 255;
814 SrcPixel.col.green = (SrcPixel.col.green * BlendFunc.SourceConstantAlpha) / 255;
815 SrcPixel.col.blue = (SrcPixel.col.blue * BlendFunc.SourceConstantAlpha) / 255;
816 SrcPixel.col.alpha = (32 == SrcBpp) ?
817 (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
818 BlendFunc.SourceConstantAlpha ;
819
820 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
821 SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha ;
822
823 DstPixel.ul = *Dst;
824 DstPixel.col.red = Clamp8((DstPixel.col.red * (255 - Alpha)) / 255 + SrcPixel.col.red) ;
825 DstPixel.col.green = Clamp8((DstPixel.col.green * (255 - Alpha)) / 255 + SrcPixel.col.green) ;
826 DstPixel.col.blue = Clamp8((DstPixel.col.blue * (255 - Alpha)) / 255 + SrcPixel.col.blue) ;
827 DstPixel.col.alpha = Clamp8((DstPixel.col.alpha * (255 - Alpha)) / 255 + SrcPixel.col.alpha) ;
828 *Dst++ = DstPixel.ul;
829 SrcX = SourceRect->left + (Cols*(SourceRect->right - SourceRect->left))/(DestRect->right - DestRect->left);
830 }
831 Dst = (PULONG)((ULONG_PTR)Dest->pvScan0 + ((DestRect->top + Rows) * Dest->lDelta) +
832 (DestRect->left << 2));
833 SrcY = SourceRect->top + (Rows*(SourceRect->bottom - SourceRect->top))/(DestRect->bottom - DestRect->top);
834 }
835
836 return TRUE;
837 }
838
839 /* EOF */
840