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