1 /*
2 * PROJECT: Win32 subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: win32ss/gdi/dib/dib24bpp.c
5 * PURPOSE: Device Independant Bitmap functions, 24bpp
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_24BPP_PutPixel(SURFOBJ * SurfObj,LONG x,LONG y,ULONG c)21 DIB_24BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
22 {
23 PBYTE addr = (PBYTE)SurfObj->pvScan0 + (y * SurfObj->lDelta) + (x << 1) + x;
24 *(PUSHORT)(addr) = c & 0xFFFF;
25 *(addr + 2) = (c >> 16) & 0xFF;
26 }
27
28 ULONG
DIB_24BPP_GetPixel(SURFOBJ * SurfObj,LONG x,LONG y)29 DIB_24BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
30 {
31 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + (x << 1) + x;
32 return *(PUSHORT)(addr) + (*(addr + 2) << 16);
33 }
34
35
36
37 VOID
DIB_24BPP_VLine(SURFOBJ * SurfObj,LONG x,LONG y1,LONG y2,ULONG c)38 DIB_24BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
39 {
40 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y1 * SurfObj->lDelta + (x << 1) + x;
41 LONG lDelta = SurfObj->lDelta;
42
43 c &= 0xFFFFFF;
44 while(y1++ < y2)
45 {
46 *(PUSHORT)(addr) = c & 0xFFFF;
47 *(addr + 2) = (BYTE)(c >> 16);
48
49 addr += lDelta;
50 }
51 }
52
53 BOOLEAN
DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)54 DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
55 {
56 LONG i, j, sx, sy, xColor, f1;
57 PBYTE SourceBits, DestBits, SourceLine, DestLine;
58 PBYTE SourceBits_4BPP, SourceLine_4BPP;
59 PWORD SourceBits_16BPP, SourceLine_16BPP;
60 BOOLEAN bTopToBottom, bLeftToRight;
61
62 DPRINT("DIB_24BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
63 BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
64 BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
65 BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
66
67 /* Get back left to right flip here */
68 bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
69
70 /* Check for top to bottom flip needed. */
71 bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
72
73 DPRINT("BltInfo->SourcePoint.x is '%d' and BltInfo->SourcePoint.y is '%d'.\n",
74 BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
75
76 /* Make WellOrdered by making top < bottom and left < right */
77 RECTL_vMakeWellOrdered(&BltInfo->DestRect);
78
79 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left * 3;
80
81 switch(BltInfo->SourceSurface->iBitmapFormat)
82 {
83 case BMF_1BPP:
84 sx = BltInfo->SourcePoint.x;
85
86 /* This sets sy to the top line */
87 sy = BltInfo->SourcePoint.y;
88
89 if (bTopToBottom)
90 {
91 /* This sets sy to the bottom line */
92 sy += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
93 }
94
95 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
96 {
97 sx = BltInfo->SourcePoint.x;
98
99 if (bLeftToRight)
100 {
101 /* This sets sx to the rightmost pixel */
102 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
103 }
104
105 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
106 {
107 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
108 {
109 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
110 } else {
111 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
112 }
113 DEC_OR_INC(sx, bLeftToRight, 1);
114 }
115 DEC_OR_INC(sy, bTopToBottom, 1);
116 }
117 break;
118
119 case BMF_4BPP:
120 DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
121 BltInfo->DestRect.right - BltInfo->DestRect.left);
122
123 /* This sets SourceBits_4BPP to the top line */
124 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
125
126 if (bTopToBottom)
127 {
128 /* This sets SourceBits_4BPP to the bottom line */
129 SourceBits_4BPP += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
130 }
131
132 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
133 {
134 SourceLine_4BPP = SourceBits_4BPP;
135 DestLine = DestBits;
136 sx = BltInfo->SourcePoint.x;
137
138 if (bLeftToRight)
139 {
140 /* This sets sx to the rightmost pixel */
141 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
142 }
143
144 f1 = sx & 1;
145
146 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
147 {
148 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
149 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
150 *DestLine++ = xColor & 0xff;
151 *(PWORD)DestLine = (WORD)(xColor >> 8);
152 DestLine += 2;
153 if(f1 == 1) {
154 DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
155 f1 = 0;
156 }
157 else
158 {
159 f1 = 1;
160 }
161 DEC_OR_INC(sx, bLeftToRight, 1);
162 }
163 DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
164 DestBits += BltInfo->DestSurface->lDelta;
165 }
166 break;
167
168 case BMF_8BPP:
169 DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n",
170 BltInfo->DestRect.right - BltInfo->DestRect.left);
171
172 /* This sets SourceLine to the top line */
173 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
174
175 if (bTopToBottom)
176 {
177 /* This sets SourceLine to the bottom line */
178 SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
179 }
180 DestLine = DestBits;
181
182 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
183 {
184 SourceBits = SourceLine;
185 DestBits = DestLine;
186
187 if (bLeftToRight)
188 {
189 /* This sets the SourceBits to the rightmost pixel */
190 SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
191 }
192
193 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
194 {
195 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits);
196 *DestBits = xColor & 0xff;
197 *(PWORD)(DestBits + 1) = (WORD)(xColor >> 8);
198 DEC_OR_INC(SourceBits, bLeftToRight, 1);
199 DestBits += 3;
200 }
201
202 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
203 DestLine += BltInfo->DestSurface->lDelta;
204 }
205 break;
206
207 case BMF_16BPP:
208 DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
209 BltInfo->DestRect.right - BltInfo->DestRect.left);
210
211 /* This sets SourceBits_16BPP to the top line */
212 SourceBits_16BPP = (PWORD)((PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x);
213
214 if (bTopToBottom)
215 {
216 /* This sets SourceBits_16BPP to the bottom line */
217 SourceBits_16BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
218 }
219
220 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
221 {
222 SourceLine_16BPP = SourceBits_16BPP;
223 DestLine = DestBits;
224
225 if (bLeftToRight)
226 {
227 /* This sets the SourceLine_16BPP to the rightmost pixel */
228 SourceLine_16BPP += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
229 }
230
231 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
232 {
233 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceLine_16BPP);
234 *DestLine++ = xColor & 0xff;
235 *(PWORD)DestLine = (WORD)(xColor >> 8);
236 DestLine += 2;
237 DEC_OR_INC(SourceLine_16BPP, bLeftToRight, 1);
238 }
239 if (bTopToBottom)
240 {
241 SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP - BltInfo->SourceSurface->lDelta);
242 }
243 else
244 {
245 SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP + BltInfo->SourceSurface->lDelta);
246 }
247 DestBits += BltInfo->DestSurface->lDelta;
248 }
249 break;
250
251 case BMF_24BPP:
252 DPRINT("24BPP Case Selected with DestRect Width of '%d'.\n",
253 BltInfo->DestRect.right - BltInfo->DestRect.left);
254
255 /* Check for no flips here because we are about to use RtlMoveMemory and it can only do increasing src & dst */
256 if ((BltInfo->XlateSourceToDest == NULL ||
257 (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
258 (!bTopToBottom && !bLeftToRight))
259 {
260 DPRINT("XO_TRIVIAL is TRUE.\n");
261 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
262 {
263 /* This sets SourceBits to the top line */
264 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
265 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
266 {
267 RtlMoveMemory(DestBits, SourceBits, 3 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
268 SourceBits += BltInfo->SourceSurface->lDelta;
269 DestBits += BltInfo->DestSurface->lDelta;
270 }
271 }
272 else
273 {
274 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
275 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 3 * BltInfo->DestRect.left;
276 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
277 {
278 RtlMoveMemory(DestBits, SourceBits, 3 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
279 SourceBits -= BltInfo->SourceSurface->lDelta;
280 DestBits -= BltInfo->DestSurface->lDelta;
281 }
282 }
283 }
284 else
285 {
286 DPRINT("XO_TRIVIAL is NOT TRUE.\n");
287
288 if (!bTopToBottom && !bLeftToRight)
289 /* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */
290 {
291 sx = BltInfo->SourcePoint.x;
292 sy = BltInfo->SourcePoint.y;
293
294 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
295 {
296 sx = BltInfo->SourcePoint.x;
297 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
298 {
299 DWORD pixel = DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy);
300 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, pixel));
301 sx++;
302 }
303 sy++;
304 }
305 }
306 else
307 {
308 /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
309 BOOL TopToBottomDone = FALSE;
310
311 if (bLeftToRight)
312 {
313 DPRINT("Flip is bLeftToRight.\n");
314 DWORD Index;
315
316 /* Allocate enough pixels for a row in DWORD's */
317 DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
318 (BltInfo->DestRect.right - BltInfo->DestRect.left + 1) * 4, TAG_DIB);
319 if (store == NULL)
320 {
321 DPRINT1("Storage Allocation Failed.\n");
322 return FALSE;
323 }
324
325 sx = BltInfo->SourcePoint.x;
326 /* This sets sy to the top line */
327 sy = BltInfo->SourcePoint.y;
328
329 /* This sets sx to the rightmost pixel */
330 sx = BltInfo->SourcePoint.x + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
331
332 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
333 {
334
335 /* This sets sx to the rightmost pixel */
336 sx = BltInfo->SourcePoint.x + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
337
338 Index = 0;
339
340 // Read right to left and store
341 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
342 {
343 store[Index] = DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy);
344 Index++;
345 sx--;
346 }
347
348 Index = 0;
349
350 // Write left to right to pixel
351 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
352 {
353 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, store[Index]));
354 Index++;
355 }
356 sy++;
357 }
358 ExFreePoolWithTag(store, TAG_DIB);
359 TopToBottomDone = TRUE;
360 }
361
362 if (bTopToBottom)
363 {
364 DPRINT("Flip is bTopToBottom.\n");
365 DWORD Index;
366
367 /* Allocate enough pixels for a column in DWORD's */
368 DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
369 (BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1) * 4, TAG_DIB);
370 if (store == NULL)
371 {
372 DPRINT1("Storage Allocation Failed.\n");
373 return FALSE;
374 }
375
376 /* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
377 * and have already completed the bLeftToRight. So we will lose our first flip output
378 * unless we work with its output which is at the destination site. So in this case
379 * our new Source becomes the previous outputs Destination.
380 */
381
382 if (TopToBottomDone)
383 {
384 sx = BltInfo->DestRect.left;
385 sy = BltInfo->DestRect.top;
386
387 /* This sets sy to the bottom line */
388 sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
389 }
390 else
391 {
392 sx = BltInfo->SourcePoint.x;
393
394 /* This sets sy to the top line */
395 sy = BltInfo->SourcePoint.y;
396
397 /* This sets sy to the bottom line */
398 sy = BltInfo->SourcePoint.y + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
399 }
400
401 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
402 {
403
404 /* This sets sy to the bottom line */
405 sy = BltInfo->SourcePoint.y + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
406 Index = 0;
407
408 /* Read bottom to top and store */
409 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
410 {
411 if (TopToBottomDone)
412 {
413 store[Index] = DIB_24BPP_GetPixel(BltInfo->DestSurface, sx, sy);
414 }
415 else
416 {
417 store[Index] = DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy);
418 }
419 Index++;
420 sy--;
421 }
422
423 Index = 0;
424
425 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
426 {
427 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, store[Index]));
428 Index++;
429 }
430 sx++;
431 }
432 ExFreePoolWithTag(store, TAG_DIB);
433 }
434
435 }
436 }
437 break;
438
439 case BMF_32BPP:
440 DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
441 BltInfo->DestRect.right - BltInfo->DestRect.left);
442
443 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
444
445 if (bTopToBottom)
446 {
447 /* This sets SourceLine to the bottom line */
448 SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
449 }
450 DestLine = DestBits;
451
452 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
453 {
454 SourceBits = SourceLine;
455 DestBits = DestLine;
456
457 if (bLeftToRight)
458 {
459 /* This sets SourceBits to the rightmost pixel */
460 SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
461 }
462 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
463 {
464 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((PDWORD) SourceBits));
465 *DestBits = xColor & 0xff;
466 *(PWORD)(DestBits + 1) = (WORD)(xColor >> 8);
467 DEC_OR_INC(SourceBits, bLeftToRight, 4);
468 DestBits += 3;
469 }
470
471 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
472 DestLine += BltInfo->DestSurface->lDelta;
473 }
474 break;
475
476 default:
477 DbgPrint("DIB_24BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
478 return FALSE;
479 }
480
481 return TRUE;
482 }
483
484 BOOLEAN
DIB_24BPP_BitBlt(PBLTINFO BltInfo)485 DIB_24BPP_BitBlt(PBLTINFO BltInfo)
486 {
487 LONG DestX, DestY;
488 LONG SourceX, SourceY;
489 LONG PatternY = 0;
490 ULONG Dest, Source = 0, Pattern = 0;
491 BOOL UsesSource;
492 BOOL UsesPattern;
493 PBYTE DestBits;
494
495 UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4);
496 UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4);
497
498 SourceY = BltInfo->SourcePoint.y;
499 DestBits = (PBYTE)(
500 (PBYTE)BltInfo->DestSurface->pvScan0 +
501 (BltInfo->DestRect.left << 1) + BltInfo->DestRect.left +
502 BltInfo->DestRect.top * BltInfo->DestSurface->lDelta);
503
504 if (UsesPattern)
505 {
506 if (BltInfo->PatternSurface)
507 {
508 PatternY = (BltInfo->DestRect.top - BltInfo->BrushOrigin.y) %
509 BltInfo->PatternSurface->sizlBitmap.cy;
510 }
511 else
512 {
513 if (BltInfo->Brush)
514 {
515 Pattern = BltInfo->Brush->iSolidColor;
516 }
517 }
518 }
519
520 for (DestY = BltInfo->DestRect.top; DestY < BltInfo->DestRect.bottom; DestY++)
521 {
522 SourceX = BltInfo->SourcePoint.x;
523
524 for (DestX = BltInfo->DestRect.left; DestX < BltInfo->DestRect.right; DestX++, DestBits += 3, SourceX++)
525 {
526 Dest = *((PUSHORT)DestBits) + (*(DestBits + 2) << 16);
527
528 if (UsesSource)
529 {
530 Source = DIB_GetSource(BltInfo->SourceSurface, SourceX, SourceY, BltInfo->XlateSourceToDest);
531 }
532
533 if (BltInfo->PatternSurface)
534 {
535 Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX - BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
536 }
537
538 Dest = DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xFFFFFF;
539 *(PUSHORT)(DestBits) = Dest & 0xFFFF;
540 *(DestBits + 2) = (BYTE)(Dest >> 16);
541 }
542
543 SourceY++;
544 if (BltInfo->PatternSurface)
545 {
546 PatternY++;
547 PatternY %= BltInfo->PatternSurface->sizlBitmap.cy;
548 }
549 DestBits -= (BltInfo->DestRect.right - BltInfo->DestRect.left) * 3;
550 DestBits += BltInfo->DestSurface->lDelta;
551 }
552
553 return TRUE;
554 }
555
556 /* BitBlt Optimize */
557 BOOLEAN
DIB_24BPP_ColorFill(SURFOBJ * DestSurface,RECTL * DestRect,ULONG color)558 DIB_24BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
559 {
560 LONG DestY;
561
562 /* Make WellOrdered by making top < bottom and left < right */
563 RECTL_vMakeWellOrdered(DestRect);
564
565 #if defined(_M_IX86) && !defined(_MSC_VER)
566 PBYTE xaddr = (PBYTE)DestSurface->pvScan0 + DestRect->top * DestSurface->lDelta + (DestRect->left << 1) + DestRect->left;
567 PBYTE addr;
568 ULONG Count;
569 ULONG xCount=DestRect->right - DestRect->left;
570
571 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
572 {
573 Count = xCount;
574 addr = xaddr;
575 xaddr = (PBYTE)((ULONG_PTR)addr + DestSurface->lDelta);
576
577 if (Count < 8)
578 {
579 /* For small fills, don't bother doing anything fancy */
580 while (Count--)
581 {
582 *(PUSHORT)(addr) = color;
583 addr += 2;
584 *(addr) = color >> 16;
585 addr += 1;
586 }
587 }
588 else
589 {
590 /* Align to 4-byte address */
591 while (0 != ((ULONG_PTR) addr & 0x3))
592 {
593 *(PUSHORT)(addr) = color;
594 addr += 2;
595 *(addr) = color >> 16;
596 addr += 1;
597 Count--;
598 }
599 /* If the color we need to fill with is 0ABC, then the final mem pattern
600 * (note little-endianness) would be:
601 *
602 * |C.B.A|C.B.A|C.B.A|C.B.A| <- pixel borders
603 * |C.B.A.C|B.A.C.B|A.C.B.A| <- ULONG borders
604 *
605 * So, taking endianness into account again, we need to fill with these
606 * ULONGs: CABC BCAB ABCA */
607
608 /* This is about 30% faster than the generic C code below */
609 __asm__ __volatile__ (
610 "movl %1, %%ecx\n\t"
611 "andl $0xffffff, %%ecx\n\t" /* 0ABC */
612 "movl %%ecx, %%ebx\n\t" /* Construct BCAB in ebx */
613 "shrl $8, %%ebx\n\t"
614 "movl %%ecx, %%eax\n\t"
615 "shll $16, %%eax\n\t"
616 "orl %%eax, %%ebx\n\t"
617 "movl %%ecx, %%edx\n\t" /* Construct ABCA in edx */
618 "shll $8, %%edx\n\t"
619 "movl %%ecx, %%eax\n\t"
620 "shrl $16, %%eax\n\t"
621 "orl %%eax, %%edx\n\t"
622 "movl %%ecx, %%eax\n\t" /* Construct CABC in eax */
623 "shll $24, %%eax\n\t"
624 "orl %%ecx, %%eax\n\t"
625 "movl %2, %%ecx\n\t" /* Load count */
626 "shr $2, %%ecx\n\t"
627 "movl %3, %%edi\n" /* Load dest */
628 "1:\n\t"
629 "movl %%eax, (%%edi)\n\t" /* Store 4 pixels, 12 bytes */
630 "movl %%ebx, 4(%%edi)\n\t"
631 "movl %%edx, 8(%%edi)\n\t"
632 "addl $12, %%edi\n\t"
633 "dec %%ecx\n\t"
634 "jnz 1b\n\t"
635 "movl %%edi, %0"
636 : "=m"(addr)
637 : "m"(color), "m"(Count), "m"(addr)
638 : "%eax", "%ebx", "%ecx", "%edx", "%edi");
639 Count = Count & 0x03;
640 while (0 != Count--)
641 {
642 *(PUSHORT)(addr) = color;
643 addr += 2;
644 *(addr) = color >> 16;
645 addr += 1;
646 }
647 }
648 }
649 #else
650
651 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
652 {
653 DIB_24BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
654 }
655 #endif
656 return TRUE;
657 }
658
659 BOOLEAN
DIB_24BPP_TransparentBlt(SURFOBJ * DestSurf,SURFOBJ * SourceSurf,RECTL * DestRect,RECTL * SourceRect,XLATEOBJ * ColorTranslation,ULONG iTransColor)660 DIB_24BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
661 RECTL* DestRect, RECTL *SourceRect,
662 XLATEOBJ *ColorTranslation, ULONG iTransColor)
663 {
664 LONG X, Y, SourceX, SourceY = 0, wd;
665 ULONG Source = 0, Dest;
666 BYTE *DestBits;
667
668 LONG DstHeight;
669 LONG DstWidth;
670 LONG SrcHeight;
671 LONG SrcWidth;
672
673 DstHeight = DestRect->bottom - DestRect->top;
674 DstWidth = DestRect->right - DestRect->left;
675 SrcHeight = SourceRect->bottom - SourceRect->top;
676 SrcWidth = SourceRect->right - SourceRect->left;
677
678 DestBits = (BYTE*)((PBYTE)DestSurf->pvScan0 +
679 (DestRect->left * 3) +
680 DestRect->top * DestSurf->lDelta);
681 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) * 3);
682
683 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
684 {
685 SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
686 for(X = DestRect->left; X < DestRect->right; X++, DestBits += 3)
687 {
688 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
689 if (SourceX >= 0 && SourceY >= 0 &&
690 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
691 {
692 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
693 if(Source != iTransColor)
694 {
695 Dest = XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFFFF;
696 *(PUSHORT)(DestBits) = Dest & 0xFFFF;
697 *(DestBits + 2) = (BYTE)(Dest >> 16);
698 }
699 }
700 }
701
702 DestBits = (BYTE*)((ULONG_PTR)DestBits + wd);
703 }
704
705 return TRUE;
706 }
707
708 typedef union {
709 ULONG ul;
710 struct {
711 UCHAR red;
712 UCHAR green;
713 UCHAR blue;
714 UCHAR alpha;
715 } col;
716 } NICEPIXEL32;
717
718 static __inline UCHAR
Clamp8(ULONG val)719 Clamp8(ULONG val)
720 {
721 return (val > 255) ? 255 : (UCHAR)val;
722 }
723
724 BOOLEAN
DIB_24BPP_AlphaBlend(SURFOBJ * Dest,SURFOBJ * Source,RECTL * DestRect,RECTL * SourceRect,CLIPOBJ * ClipRegion,XLATEOBJ * ColorTranslation,BLENDOBJ * BlendObj)725 DIB_24BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
726 RECTL* SourceRect, CLIPOBJ* ClipRegion,
727 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
728 {
729 INT Rows, Cols, SrcX, SrcY;
730 register PUCHAR Dst;
731 BLENDFUNCTION BlendFunc;
732 register NICEPIXEL32 DstPixel, SrcPixel;
733 UCHAR Alpha;
734 //UCHAR SrcBpp;
735
736 DPRINT("DIB_24BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
737 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
738 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
739
740 BlendFunc = BlendObj->BlendFunction;
741 if (BlendFunc.BlendOp != AC_SRC_OVER)
742 {
743 DPRINT1("BlendOp != AC_SRC_OVER\n");
744 return FALSE;
745 }
746 if (BlendFunc.BlendFlags != 0)
747 {
748 DPRINT1("BlendFlags != 0\n");
749 return FALSE;
750 }
751 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
752 {
753 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
754 return FALSE;
755 }
756 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
757 BitsPerFormat(Source->iBitmapFormat) != 32)
758 {
759 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
760 return FALSE;
761 }
762
763 Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
764 (DestRect->left * 3));
765 //SrcBpp = BitsPerFormat(Source->iBitmapFormat);
766
767 Rows = 0;
768 SrcY = SourceRect->top;
769 while (++Rows <= DestRect->bottom - DestRect->top)
770 {
771 Cols = 0;
772 SrcX = SourceRect->left;
773 while (++Cols <= DestRect->right - DestRect->left)
774 {
775 SrcPixel.ul = DIB_GetSource(Source, SrcX, SrcY, ColorTranslation);
776 SrcPixel.col.red = (SrcPixel.col.red * BlendFunc.SourceConstantAlpha) / 255;
777 SrcPixel.col.green = (SrcPixel.col.green * BlendFunc.SourceConstantAlpha) / 255;
778 SrcPixel.col.blue = (SrcPixel.col.blue * BlendFunc.SourceConstantAlpha) / 255;
779 if (!(BlendFunc.AlphaFormat & AC_SRC_ALPHA))
780 {
781 Alpha = BlendFunc.SourceConstantAlpha ;
782 }
783 else
784 {
785 Alpha = (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha) / 255;
786 }
787
788 DstPixel.col.red = Clamp8((*Dst * (255 - Alpha)) / 255 + SrcPixel.col.red) ;
789 DstPixel.col.green = Clamp8((*(Dst+1) * (255 - Alpha) / 255 + SrcPixel.col.green)) ;
790 DstPixel.col.blue = Clamp8((*(Dst+2) * (255 - Alpha)) / 255 + SrcPixel.col.blue) ;
791 *Dst++ = DstPixel.col.red;
792 *Dst++ = DstPixel.col.green;
793 *Dst++ = DstPixel.col.blue;
794 SrcX = SourceRect->left + (Cols*(SourceRect->right - SourceRect->left))/(DestRect->right - DestRect->left);
795 }
796 Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + ((DestRect->top + Rows) * Dest->lDelta) +
797 (DestRect->left*3));
798 SrcY = SourceRect->top + (Rows*(SourceRect->bottom - SourceRect->top))/(DestRect->bottom - DestRect->top);
799 }
800
801 return TRUE;
802 }
803
804 /* EOF */
805