- Merge to trunk r37270.
[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 = 0;
418 LONG sy = 0;
419 LONG DesX;
420 LONG DesY;
421
422 LONG SrcZoomXHight;
423 LONG SrcZoomXLow;
424 LONG SrcZoomYHight;
425 LONG SrcZoomYLow;
426
427 LONG sy_dec = 0;
428 LONG sy_max;
429
430 LONG sx_dec = 0;
431 LONG sx_max;
432 ULONG color;
433
434 DPRINT("DIB_24BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
435 BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
436 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
437
438 /* Calc the Zoom height of Source */
439 SrcSizeY = SourceRect->bottom - SourceRect->top;
440
441 /* Calc the Zoom Width of Source */
442 SrcSizeX = SourceRect->right - SourceRect->left;
443
444 /* Calc the Zoom height of Destinations */
445 DesSizeY = DestRect->bottom - DestRect->top;
446
447 /* Calc the Zoom width of Destinations */
448 DesSizeX = DestRect->right - DestRect->left;
449
450 /* Calc the zoom factor of source height */
451 SrcZoomYHight = SrcSizeY / DesSizeY;
452 SrcZoomYLow = SrcSizeY - (SrcZoomYHight * DesSizeY);
453
454 /* Calc the zoom factor of source width */
455 SrcZoomXHight = SrcSizeX / DesSizeX;
456 SrcZoomXLow = SrcSizeX - (SrcZoomXHight * DesSizeX);
457
458 sx_max = DesSizeX;
459 sy_max = DesSizeY;
460 sy = SourceRect->top;
461
462 switch(SourceSurf->iBitmapFormat)
463 {
464 case BMF_1BPP:
465 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
466 /* This is a reference implementation, it hasn't been optimized for speed */
467
468 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
469 {
470 sx = SourceRect->left;
471 sx_dec = 0;
472
473 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
474 {
475 color = XLATEOBJ_iXlate(ColorTranslation,
476 DIB_1BPP_GetPixel(SourceSurf, sx, sy));
477
478 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, color);
479
480 sx += SrcZoomXHight;
481 sx_dec += SrcZoomXLow;
482 if (sx_dec >= sx_max)
483 {
484 sx++;
485 sx_dec -= sx_max;
486 }
487 }
488
489 sy += SrcZoomYHight;
490 sy_dec += SrcZoomYLow;
491 if (sy_dec >= sy_max)
492 {
493 sy++;
494 sy_dec -= sy_max;
495 }
496 }
497
498 break;
499
500 case BMF_4BPP:
501 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
502 /* This is a reference implementation, it hasn't been optimized for speed */
503
504 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
505 {
506 sx = SourceRect->left;
507 sx_dec = 0;
508
509 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
510 {
511 color = XLATEOBJ_iXlate(ColorTranslation,
512 DIB_4BPP_GetPixel(SourceSurf, sx, sy));
513
514 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, color);
515
516 sx += SrcZoomXHight;
517 sx_dec += SrcZoomXLow;
518 if (sx_dec >= sx_max)
519 {
520 sx++;
521 sx_dec -= sx_max;
522 }
523 }
524
525 sy += SrcZoomYHight;
526 sy_dec += SrcZoomYLow;
527 if (sy_dec >= sy_max)
528 {
529 sy++;
530 sy_dec -= sy_max;
531 }
532 }
533 break;
534
535 case BMF_8BPP:
536 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
537 /* This is a reference implementation, it hasn't been optimized for speed */
538
539 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
540 {
541 sx = SourceRect->left;
542 sx_dec = 0;
543
544 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
545 {
546 color = XLATEOBJ_iXlate(ColorTranslation,
547 DIB_8BPP_GetPixel(SourceSurf, sx, sy));
548
549 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, color);
550
551 sx += SrcZoomXHight;
552 sx_dec += SrcZoomXLow;
553 if (sx_dec >= sx_max)
554 {
555 sx++;
556 sx_dec -= sx_max;
557 }
558 }
559
560 sy += SrcZoomYHight;
561 sy_dec += SrcZoomYLow;
562 if (sy_dec >= sy_max)
563 {
564 sy++;
565 sy_dec -= sy_max;
566 }
567 }
568 break;
569
570 case BMF_16BPP:
571 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
572 /* This is a reference implementation, it hasn't been optimized for speed */
573
574 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
575 {
576 sx = SourceRect->left;
577 sx_dec = 0;
578
579 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
580 {
581 color = XLATEOBJ_iXlate(ColorTranslation,
582 DIB_16BPP_GetPixel(SourceSurf, sx, sy));
583
584 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, color);
585
586 sx += SrcZoomXHight;
587 sx_dec += SrcZoomXLow;
588 if (sx_dec >= sx_max)
589 {
590 sx++;
591 sx_dec -= sx_max;
592 }
593 }
594
595 sy += SrcZoomYHight;
596 sy_dec += SrcZoomYLow;
597 if (sy_dec >= sy_max)
598 {
599 sy++;
600 sy_dec -= sy_max;
601 }
602 }
603 break;
604
605 case BMF_24BPP:
606 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
607 /* This is a reference implementation, it hasn't been optimized for speed */
608
609 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
610 {
611 sx = SourceRect->left;
612 sx_dec = 0;
613
614 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
615 {
616 color = XLATEOBJ_iXlate(ColorTranslation,
617 DIB_24BPP_GetPixel(SourceSurf, sx, sy));
618
619 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, color);
620
621 sx += SrcZoomXHight;
622 sx_dec += SrcZoomXLow;
623 if (sx_dec >= sx_max)
624 {
625 sx++;
626 sx_dec -= sx_max;
627 }
628 }
629
630 sy += SrcZoomYHight;
631 sy_dec += SrcZoomYLow;
632 if (sy_dec >= sy_max)
633 {
634 sy++;
635 sy_dec -= sy_max;
636 }
637 }
638 break;
639
640 case BMF_32BPP:
641 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
642 /* This is a reference implementation, it hasn't been optimized for speed */
643
644 for (DesY=DestRect->top; DesY<DestRect->bottom; DesY++)
645 {
646 sx = SourceRect->left;
647 sx_dec = 0;
648
649 for (DesX=DestRect->left; DesX<DestRect->right; DesX++)
650 {
651 color = XLATEOBJ_iXlate(ColorTranslation,
652 DIB_32BPP_GetPixel(SourceSurf, sx, sy));
653
654 DIB_24BPP_PutPixel(DestSurf, DesX, DesY, color);
655
656 sx += SrcZoomXHight;
657 sx_dec += SrcZoomXLow;
658 if (sx_dec >= sx_max)
659 {
660 sx++;
661 sx_dec -= sx_max;
662 }
663 }
664
665 sy += SrcZoomYHight;
666 sy_dec += SrcZoomYLow;
667 if (sy_dec >= sy_max)
668 {
669 sy++;
670 sy_dec -= sy_max;
671 }
672 }
673 break;
674
675 default:
676 DPRINT1("DIB_24BPP_StretchBlt: Unhandled Source BPP: %u\n", BitsPerFormat(SourceSurf->iBitmapFormat));
677 return FALSE;
678 }
679
680 return TRUE;
681 }
682
683 BOOLEAN
684 DIB_24BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
685 RECTL* DestRect, POINTL *SourcePoint,
686 XLATEOBJ *ColorTranslation, ULONG iTransColor)
687 {
688 ULONG X, Y, SourceX, SourceY, Source, wd, Dest;
689 BYTE *DestBits;
690
691 SourceY = SourcePoint->y;
692 DestBits = (BYTE*)((PBYTE)DestSurf->pvScan0 +
693 (DestRect->left * 3) +
694 DestRect->top * DestSurf->lDelta);
695 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) * 3);
696
697 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
698 {
699 SourceX = SourcePoint->x;
700 for(X = DestRect->left; X < DestRect->right; X++, DestBits += 3, SourceX++)
701 {
702 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
703 if(Source != iTransColor)
704 {
705 Dest = XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFFFF;
706 *(PUSHORT)(DestBits) = Dest & 0xFFFF;
707 *(DestBits + 2) = Dest >> 16;
708 }
709 }
710
711 SourceY++;
712 DestBits = (BYTE*)((ULONG_PTR)DestBits + wd);
713 }
714
715 return TRUE;
716 }
717
718 typedef union {
719 ULONG ul;
720 struct {
721 UCHAR red;
722 UCHAR green;
723 UCHAR blue;
724 UCHAR alpha;
725 } col;
726 } NICEPIXEL32;
727
728 static __inline UCHAR
729 Clamp8(ULONG val)
730 {
731 return (val > 255) ? 255 : val;
732 }
733
734 BOOLEAN
735 DIB_24BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
736 RECTL* SourceRect, CLIPOBJ* ClipRegion,
737 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
738 {
739 INT Rows, Cols, SrcX, SrcY;
740 register PUCHAR Dst;
741 ULONG DstDelta;
742 BLENDFUNCTION BlendFunc;
743 register NICEPIXEL32 DstPixel, SrcPixel;
744 UCHAR Alpha, SrcBpp;
745
746 DPRINT("DIB_24BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
747 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
748 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
749
750 ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
751 DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
752
753 BlendFunc = BlendObj->BlendFunction;
754 if (BlendFunc.BlendOp != AC_SRC_OVER)
755 {
756 DPRINT1("BlendOp != AC_SRC_OVER\n");
757 return FALSE;
758 }
759 if (BlendFunc.BlendFlags != 0)
760 {
761 DPRINT1("BlendFlags != 0\n");
762 return FALSE;
763 }
764 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
765 {
766 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
767 return FALSE;
768 }
769 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
770 BitsPerFormat(Source->iBitmapFormat) != 32)
771 {
772 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
773 return FALSE;
774 }
775
776 Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
777 (DestRect->left * 3));
778 DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) * 3);
779 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
780
781 Rows = DestRect->bottom - DestRect->top;
782 SrcY = SourceRect->top;
783 while (--Rows >= 0)
784 {
785 Cols = DestRect->right - DestRect->left;
786 SrcX = SourceRect->left;
787 while (--Cols >= 0)
788 {
789 SrcPixel.ul = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
790 SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
791 SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
792 SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
793 SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
794
795 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
796 SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
797
798 /* copy only 24bits of dst */
799 DstPixel.ul = *(PUSHORT)(Dst) + (*(Dst+2) << 16);
800 DstPixel.col.red = Clamp8(DstPixel.col.red * (255 - Alpha) / 255 + SrcPixel.col.red);
801 DstPixel.col.green = Clamp8(DstPixel.col.green * (255 - Alpha) / 255 + SrcPixel.col.green);
802 DstPixel.col.blue = Clamp8(DstPixel.col.blue * (255 - Alpha) / 255 + SrcPixel.col.blue);
803 /* copy back 24bits of result */
804 *(PUSHORT)(Dst) = (USHORT)(DstPixel.ul & 0xFFFF);
805 *(Dst + 2) = (UCHAR)((DstPixel.ul >> 16) & 0xFF);
806 Dst = (PUCHAR)((ULONG_PTR)Dst + 3);
807 }
808 Dst = (PUCHAR)((ULONG_PTR)Dst + DstDelta);
809 SrcY++;
810 }
811
812 return TRUE;
813 }
814
815 /* EOF */