Don't read and copy 32 Bit blocks, but only 24 Bit according to
[reactos.git] / reactos / subsystems / win32 / win32k / dib / dib24bpp.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$ */
20
21 #include <w32k.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 VOID
27 DIB_24BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
28 {
29 PBYTE addr = (PBYTE)SurfObj->pvScan0 + (y * SurfObj->lDelta) + (x << 1) + x;
30 *(PUSHORT)(addr) = c & 0xFFFF;
31 *(addr + 2) = (c >> 16) & 0xFF;
32 }
33
34 ULONG
35 DIB_24BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
36 {
37 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + (x << 1) + x;
38 return *(PUSHORT)(addr) + (*(addr + 2) << 16);
39 }
40
41
42
43 VOID
44 DIB_24BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
45 {
46 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y1 * SurfObj->lDelta + (x << 1) + x;
47 LONG lDelta = SurfObj->lDelta;
48
49 c &= 0xFFFFFF;
50 while(y1++ < y2) {
51 *(PUSHORT)(addr) = c & 0xFFFF;
52 *(addr + 2) = c >> 16;
53
54 addr += lDelta;
55 }
56 }
57
58 BOOLEAN
59 DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
60 {
61 LONG i, j, sx, sy, xColor, f1;
62 PBYTE SourceBits, DestBits, SourceLine, DestLine;
63 PBYTE SourceBits_4BPP, SourceLine_4BPP;
64 PWORD SourceBits_16BPP, SourceLine_16BPP;
65
66 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left * 3;
67
68 switch(BltInfo->SourceSurface->iBitmapFormat)
69 {
70 case BMF_1BPP:
71 sx = BltInfo->SourcePoint.x;
72 sy = BltInfo->SourcePoint.y;
73
74 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
75 {
76 sx = BltInfo->SourcePoint.x;
77 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
78 {
79 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
80 {
81 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
82 } else {
83 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
84 }
85 sx++;
86 }
87 sy++;
88 }
89 break;
90
91 case BMF_4BPP:
92 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
93
94 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
95 {
96 SourceLine_4BPP = SourceBits_4BPP;
97 DestLine = DestBits;
98 sx = BltInfo->SourcePoint.x;
99 f1 = sx & 1;
100
101 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
102 {
103 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
104 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
105 *DestLine++ = xColor & 0xff;
106 *(PWORD)DestLine = xColor >> 8;
107 DestLine += 2;
108 if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
109 sx++;
110 }
111
112 SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
113 DestBits += BltInfo->DestSurface->lDelta;
114 }
115 break;
116
117 case BMF_8BPP:
118 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
119 DestLine = DestBits;
120
121 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
122 {
123 SourceBits = SourceLine;
124 DestBits = DestLine;
125
126 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
127 {
128 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits);
129 *DestBits = xColor & 0xff;
130 *(PWORD)(DestBits + 1) = xColor >> 8;
131 SourceBits += 1;
132 DestBits += 3;
133 }
134
135 SourceLine += BltInfo->SourceSurface->lDelta;
136 DestLine += BltInfo->DestSurface->lDelta;
137 }
138 break;
139
140 case BMF_16BPP:
141 SourceBits_16BPP = (PWORD)((PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x);
142
143 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
144 {
145 SourceLine_16BPP = SourceBits_16BPP;
146 DestLine = DestBits;
147
148 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
149 {
150 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceLine_16BPP);
151 *DestLine++ = xColor & 0xff;
152 *(PWORD)DestLine = xColor >> 8;
153 DestLine += 2;
154 SourceLine_16BPP++;
155 }
156
157 SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP + BltInfo->SourceSurface->lDelta);
158 DestBits += BltInfo->DestSurface->lDelta;
159 }
160 break;
161
162 case BMF_24BPP:
163 if (NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
164 {
165 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
166 {
167 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
168 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
169 {
170 RtlMoveMemory(DestBits, SourceBits, 3 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
171 SourceBits += BltInfo->SourceSurface->lDelta;
172 DestBits += BltInfo->DestSurface->lDelta;
173 }
174 }
175 else
176 {
177 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
178 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 3 * BltInfo->DestRect.left;
179 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
180 {
181 RtlMoveMemory(DestBits, SourceBits, 3 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
182 SourceBits -= BltInfo->SourceSurface->lDelta;
183 DestBits -= BltInfo->DestSurface->lDelta;
184 }
185 }
186 }
187 else
188 {
189 sx = BltInfo->SourcePoint.x;
190 sy = BltInfo->SourcePoint.y;
191
192 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
193 {
194 sx = BltInfo->SourcePoint.x;
195 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
196 {
197 DWORD pixel = DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy);
198 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, pixel));
199 sx++;
200 }
201 sy++;
202 }
203 }
204 break;
205
206 case BMF_32BPP:
207 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
208 DestLine = DestBits;
209
210 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
211 {
212 SourceBits = SourceLine;
213 DestBits = DestLine;
214
215 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
216 {
217 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((PDWORD) SourceBits));
218 *DestBits = xColor & 0xff;
219 *(PWORD)(DestBits + 1) = xColor >> 8;
220 SourceBits += 4;
221 DestBits += 3;
222 }
223
224 SourceLine += BltInfo->SourceSurface->lDelta;
225 DestLine += BltInfo->DestSurface->lDelta;
226 }
227 break;
228
229 default:
230 DbgPrint("DIB_24BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
231 return FALSE;
232 }
233
234 return TRUE;
235 }
236
237 BOOLEAN
238 DIB_24BPP_BitBlt(PBLTINFO BltInfo)
239 {
240 ULONG DestX, DestY;
241 ULONG SourceX, SourceY;
242 ULONG PatternY = 0;
243 ULONG Dest, Source = 0, Pattern = 0;
244 BOOL UsesSource;
245 BOOL UsesPattern;
246 PBYTE DestBits;
247
248 UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4);
249 UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4);
250
251 SourceY = BltInfo->SourcePoint.y;
252 DestBits = (PBYTE)(
253 (PBYTE)BltInfo->DestSurface->pvScan0 +
254 (BltInfo->DestRect.left << 1) + BltInfo->DestRect.left +
255 BltInfo->DestRect.top * BltInfo->DestSurface->lDelta);
256
257 if (UsesPattern)
258 {
259 if (BltInfo->PatternSurface)
260 {
261 PatternY = (BltInfo->DestRect.top + BltInfo->BrushOrigin.y) %
262 BltInfo->PatternSurface->sizlBitmap.cy;
263 }
264 else
265 {
266 Pattern = BltInfo->Brush->iSolidColor;
267 }
268 }
269
270 for (DestY = BltInfo->DestRect.top; DestY < BltInfo->DestRect.bottom; DestY++)
271 {
272 SourceX = BltInfo->SourcePoint.x;
273
274 for (DestX = BltInfo->DestRect.left; DestX < BltInfo->DestRect.right; DestX++, DestBits += 3, SourceX++)
275 {
276 Dest = *((PUSHORT)DestBits) + (*(DestBits + 2) << 16);
277
278 if (UsesSource)
279 {
280 Source = DIB_GetSource(BltInfo->SourceSurface, SourceX, SourceY, BltInfo->XlateSourceToDest);
281 }
282
283 if (BltInfo->PatternSurface)
284 {
285 Pattern = DIB_GetSource(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY, BltInfo->XlatePatternToDest);
286 }
287
288 Dest = DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xFFFFFF;
289 *(PUSHORT)(DestBits) = Dest & 0xFFFF;
290 *(DestBits + 2) = Dest >> 16;
291 }
292
293 SourceY++;
294 if (BltInfo->PatternSurface)
295 {
296 PatternY++;
297 PatternY %= BltInfo->PatternSurface->sizlBitmap.cy;
298 }
299 DestBits -= (BltInfo->DestRect.right - BltInfo->DestRect.left) * 3;
300 DestBits += BltInfo->DestSurface->lDelta;
301 }
302
303 return TRUE;
304 }
305
306 /* BitBlt Optimize */
307 BOOLEAN
308 DIB_24BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
309 {
310 ULONG DestY;
311
312 #if defined(_M_IX86) && !defined(_MSC_VER)
313 PBYTE xaddr = (PBYTE)DestSurface->pvScan0 + DestRect->top * DestSurface->lDelta + (DestRect->left << 1) + DestRect->left;
314 PBYTE addr;
315 ULONG Count;
316 ULONG xCount=DestRect->right - DestRect->left;
317
318 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
319 {
320 Count = xCount;
321 addr = xaddr;
322 xaddr = (PBYTE)((ULONG_PTR)addr + DestSurface->lDelta);
323
324 if (Count < 8)
325 {
326 /* For small fills, don't bother doing anything fancy */
327 while (Count--)
328 {
329 *(PUSHORT)(addr) = color;
330 addr += 2;
331 *(addr) = color >> 16;
332 addr += 1;
333 }
334 }
335 else
336 {
337 /* Align to 4-byte address */
338 while (0 != ((ULONG_PTR) addr & 0x3))
339 {
340 *(PUSHORT)(addr) = color;
341 addr += 2;
342 *(addr) = color >> 16;
343 addr += 1;
344 Count--;
345 }
346 /* If the color we need to fill with is 0ABC, then the final mem pattern
347 * (note little-endianness) would be:
348 *
349 * |C.B.A|C.B.A|C.B.A|C.B.A| <- pixel borders
350 * |C.B.A.C|B.A.C.B|A.C.B.A| <- ULONG borders
351 *
352 * So, taking endianness into account again, we need to fill with these
353 * ULONGs: CABC BCAB ABCA */
354
355 /* This is about 30% faster than the generic C code below */
356 __asm__ __volatile__ (
357 " movl %1, %%ecx\n"
358 " andl $0xffffff, %%ecx\n" /* 0ABC */
359 " movl %%ecx, %%ebx\n" /* Construct BCAB in ebx */
360 " shrl $8, %%ebx\n"
361 " movl %%ecx, %%eax\n"
362 " shll $16, %%eax\n"
363 " orl %%eax, %%ebx\n"
364 " movl %%ecx, %%edx\n" /* Construct ABCA in edx */
365 " shll $8, %%edx\n"
366 " movl %%ecx, %%eax\n"
367 " shrl $16, %%eax\n"
368 " orl %%eax, %%edx\n"
369 " movl %%ecx, %%eax\n" /* Construct CABC in eax */
370 " shll $24, %%eax\n"
371 " orl %%ecx, %%eax\n"
372 " movl %2, %%ecx\n" /* Load count */
373 " shr $2, %%ecx\n"
374 " movl %3, %%edi\n" /* Load dest */
375 ".FL1:\n"
376 " movl %%eax, (%%edi)\n" /* Store 4 pixels, 12 bytes */
377 " movl %%ebx, 4(%%edi)\n"
378 " movl %%edx, 8(%%edi)\n"
379 " addl $12, %%edi\n"
380 " dec %%ecx\n"
381 " jnz .FL1\n"
382 " movl %%edi, %0\n"
383 : "=m"(addr)
384 : "m"(color), "m"(Count), "m"(addr)
385 : "%eax", "%ebx", "%ecx", "%edx", "%edi");
386 Count = Count & 0x03;
387 while (0 != Count--)
388 {
389 *(PUSHORT)(addr) = color;
390 addr += 2;
391 *(addr) = color >> 16;
392 addr += 1;
393 }
394 }
395 }
396 #else
397
398 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
399 {
400 DIB_24BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
401 }
402 #endif
403 return TRUE;
404 }
405
406 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
407 BOOLEAN DIB_24BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
408 RECTL* DestRect, RECTL *SourceRect,
409 POINTL* MaskOrigin, POINTL BrushOrigin,
410 CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
411 ULONG Mode)
412 {
413 LONG SrcSizeY;
414 LONG SrcSizeX;
415 LONG DesSizeY;
416 LONG DesSizeX;
417 LONG sx;
418 LONG sy;
419 LONG DesX;
420 LONG DesY;
421 LONG color;
422
423 SrcSizeY = SourceRect->bottom - SourceRect->top;
424 SrcSizeX = SourceRect->right - SourceRect->left;
425
426 DesSizeY = DestRect->bottom - DestRect->top;
427 DesSizeX = DestRect->right - DestRect->left;
428
429 switch(SourceSurf->iBitmapFormat)
430 {
431 case BMF_1BPP:
432 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
433 /* This is a reference implementation, it hasn't been optimized for speed */
434
435 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
436 {
437 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
438
439 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
440 {
441 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
442
443 if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
444 {
445 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, 0));
446 }
447 else
448 {
449 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, 1));
450 }
451 }
452 }
453
454 break;
455
456 case BMF_4BPP:
457 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
458 /* This is a reference implementation, it hasn't been optimized for speed */
459
460 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
461 {
462 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
463
464 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
465 {
466 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
467 color = DIB_4BPP_GetPixel(SourceSurf, sx, sy);
468 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, color));
469 }
470 }
471 break;
472
473 case BMF_8BPP:
474 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
475 /* This is a reference implementation, it hasn't been optimized for speed */
476
477 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
478 {
479 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
480
481 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
482 {
483 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
484 color = DIB_8BPP_GetPixel(SourceSurf, sx, sy);
485 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, color));
486 }
487 }
488 break;
489
490 case BMF_16BPP:
491 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
492 /* This is a reference implementation, it hasn't been optimized for speed */
493
494 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
495 {
496 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
497
498 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
499 {
500 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
501 color = DIB_16BPP_GetPixel(SourceSurf, sx, sy);
502 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, color));
503 }
504 }
505 break;
506
507 case BMF_24BPP:
508 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
509 /* This is a reference implementation, it hasn't been optimized for speed */
510
511 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
512 {
513 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
514
515 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
516 {
517 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
518 color = DIB_24BPP_GetPixel(SourceSurf, sx, sy);
519 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, color));
520 }
521 }
522 break;
523
524 case BMF_32BPP:
525 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
526 /* This is a reference implementation, it hasn't been optimized for speed */
527
528 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
529 {
530 sy = (((DesY - DestRect->top) * SrcSizeY) / DesSizeY) + SourceRect->top;
531
532 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
533 {
534 sx = (((DesX - DestRect->left) * SrcSizeX) / DesSizeX) + SourceRect->left;
535 color = DIB_32BPP_GetPixel(SourceSurf, sx, sy);
536 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, XLATEOBJ_iXlate(ColorTranslation, color));
537 }
538 }
539 break;
540
541 default:
542 //DPRINT1("DIB_24BPP_StretchBlt: Unhandled Source BPP: %u\n", BitsPerFormat(SourceSurf->iBitmapFormat));
543 return FALSE;
544 }
545
546 return TRUE;
547 }
548
549 BOOLEAN
550 DIB_24BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
551 RECTL* DestRect, POINTL *SourcePoint,
552 XLATEOBJ *ColorTranslation, ULONG iTransColor)
553 {
554 ULONG X, Y, SourceX, SourceY, Source, wd, Dest;
555 BYTE *DestBits;
556
557 SourceY = SourcePoint->y;
558 DestBits = (BYTE*)((PBYTE)DestSurf->pvScan0 +
559 (DestRect->left << 2) +
560 DestRect->top * DestSurf->lDelta);
561 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 2);
562
563 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
564 {
565 SourceX = SourcePoint->x;
566 for(X = DestRect->left; X < DestRect->right; X++, DestBits += 3, SourceX++)
567 {
568 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
569 if(Source != iTransColor)
570 {
571 Dest = XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFFFF;
572 *(PUSHORT)(DestBits) = Dest & 0xFFFF;
573 *(DestBits + 2) = Dest >> 16;
574 }
575 }
576
577 SourceY++;
578 DestBits = (BYTE*)((ULONG_PTR)DestBits + wd);
579 }
580
581 return TRUE;
582 }
583
584 typedef union {
585 ULONG ul;
586 struct {
587 UCHAR red;
588 UCHAR green;
589 UCHAR blue;
590 UCHAR alpha;
591 } col;
592 } NICEPIXEL32;
593
594 static __inline UCHAR
595 Clamp8(ULONG val)
596 {
597 return (val > 255) ? 255 : val;
598 }
599
600 BOOLEAN
601 DIB_24BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
602 RECTL* SourceRect, CLIPOBJ* ClipRegion,
603 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
604 {
605 INT Rows, Cols, SrcX, SrcY;
606 register PUCHAR Dst;
607 ULONG DstDelta;
608 BLENDFUNCTION BlendFunc;
609 register NICEPIXEL32 DstPixel, SrcPixel;
610 UCHAR Alpha, SrcBpp;
611
612 DPRINT("DIB_24BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
613 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
614 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
615
616 ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
617 DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
618
619 BlendFunc = BlendObj->BlendFunction;
620 if (BlendFunc.BlendOp != AC_SRC_OVER)
621 {
622 DPRINT1("BlendOp != AC_SRC_OVER\n");
623 return FALSE;
624 }
625 if (BlendFunc.BlendFlags != 0)
626 {
627 DPRINT1("BlendFlags != 0\n");
628 return FALSE;
629 }
630 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
631 {
632 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
633 return FALSE;
634 }
635 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
636 BitsPerFormat(Source->iBitmapFormat) != 32)
637 {
638 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
639 return FALSE;
640 }
641
642 Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
643 (DestRect->left * 3));
644 DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) * 3);
645 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
646
647 Rows = DestRect->bottom - DestRect->top;
648 SrcY = SourceRect->top;
649 while (--Rows >= 0)
650 {
651 Cols = DestRect->right - DestRect->left;
652 SrcX = SourceRect->left;
653 while (--Cols >= 0)
654 {
655 SrcPixel.ul = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
656 SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
657 SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
658 SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
659 SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
660
661 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
662 SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
663
664 /* copy only 24bits of dst */
665 DstPixel.ul = *(PUSHORT)(Dst) + (*(Dst+2) << 16);
666 DstPixel.col.red = Clamp8(DstPixel.col.red * (255 - Alpha) / 255 + SrcPixel.col.red);
667 DstPixel.col.green = Clamp8(DstPixel.col.green * (255 - Alpha) / 255 + SrcPixel.col.green);
668 DstPixel.col.blue = Clamp8(DstPixel.col.blue * (255 - Alpha) / 255 + SrcPixel.col.blue);
669 /* copy back 24bits of result */
670 *(PUSHORT)(Dst) = (USHORT)(DstPixel.ul & 0xFFFF);
671 *(Dst + 2) = (UCHAR)((DstPixel.ul >> 16) & 0xFF);
672 Dst = (PUCHAR)((ULONG_PTR)Dst + 3);
673 }
674 Dst = (PUCHAR)((ULONG_PTR)Dst + DstDelta);
675 SrcY++;
676 }
677
678 return TRUE;
679 }
680
681 /* EOF */