d3c60d43236573f3a5ae9f8abcf0979c52430dde
[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 BOOLEAN
407 DIB_24BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
408 RECTL* DestRect, POINTL *SourcePoint,
409 XLATEOBJ *ColorTranslation, ULONG iTransColor)
410 {
411 ULONG X, Y, SourceX, SourceY, Source, wd, Dest;
412 BYTE *DestBits;
413
414 SourceY = SourcePoint->y;
415 DestBits = (BYTE*)((PBYTE)DestSurf->pvScan0 +
416 (DestRect->left * 3) +
417 DestRect->top * DestSurf->lDelta);
418 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) * 3);
419
420 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
421 {
422 SourceX = SourcePoint->x;
423 for(X = DestRect->left; X < DestRect->right; X++, DestBits += 3, SourceX++)
424 {
425 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
426 if(Source != iTransColor)
427 {
428 Dest = XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFFFF;
429 *(PUSHORT)(DestBits) = Dest & 0xFFFF;
430 *(DestBits + 2) = Dest >> 16;
431 }
432 }
433
434 SourceY++;
435 DestBits = (BYTE*)((ULONG_PTR)DestBits + wd);
436 }
437
438 return TRUE;
439 }
440
441 typedef union {
442 ULONG ul;
443 struct {
444 UCHAR red;
445 UCHAR green;
446 UCHAR blue;
447 UCHAR alpha;
448 } col;
449 } NICEPIXEL32;
450
451 static __inline UCHAR
452 Clamp8(ULONG val)
453 {
454 return (val > 255) ? 255 : val;
455 }
456
457 BOOLEAN
458 DIB_24BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
459 RECTL* SourceRect, CLIPOBJ* ClipRegion,
460 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
461 {
462 INT Rows, Cols, SrcX, SrcY;
463 register PUCHAR Dst;
464 ULONG DstDelta;
465 BLENDFUNCTION BlendFunc;
466 register NICEPIXEL32 DstPixel, SrcPixel;
467 UCHAR Alpha, SrcBpp;
468
469 DPRINT("DIB_24BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
470 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
471 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
472
473 ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
474 DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
475
476 BlendFunc = BlendObj->BlendFunction;
477 if (BlendFunc.BlendOp != AC_SRC_OVER)
478 {
479 DPRINT1("BlendOp != AC_SRC_OVER\n");
480 return FALSE;
481 }
482 if (BlendFunc.BlendFlags != 0)
483 {
484 DPRINT1("BlendFlags != 0\n");
485 return FALSE;
486 }
487 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
488 {
489 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
490 return FALSE;
491 }
492 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
493 BitsPerFormat(Source->iBitmapFormat) != 32)
494 {
495 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
496 return FALSE;
497 }
498
499 Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
500 (DestRect->left * 3));
501 DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) * 3);
502 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
503
504 Rows = DestRect->bottom - DestRect->top;
505 SrcY = SourceRect->top;
506 while (--Rows >= 0)
507 {
508 Cols = DestRect->right - DestRect->left;
509 SrcX = SourceRect->left;
510 while (--Cols >= 0)
511 {
512 SrcPixel.ul = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
513 SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
514 SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
515 SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
516 SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
517
518 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
519 SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
520
521 /* copy only 24bits of dst */
522 DstPixel.ul = *(PUSHORT)(Dst) + (*(Dst+2) << 16);
523 DstPixel.col.red = Clamp8(DstPixel.col.red * (255 - Alpha) / 255 + SrcPixel.col.red);
524 DstPixel.col.green = Clamp8(DstPixel.col.green * (255 - Alpha) / 255 + SrcPixel.col.green);
525 DstPixel.col.blue = Clamp8(DstPixel.col.blue * (255 - Alpha) / 255 + SrcPixel.col.blue);
526 /* copy back 24bits of result */
527 *(PUSHORT)(Dst) = (USHORT)(DstPixel.ul & 0xFFFF);
528 *(Dst + 2) = (UCHAR)((DstPixel.ul >> 16) & 0xFF);
529 Dst = (PUCHAR)((ULONG_PTR)Dst + 3);
530 }
531 Dst = (PUCHAR)((ULONG_PTR)Dst + DstDelta);
532 SrcY++;
533 }
534
535 return TRUE;
536 }
537
538 /* EOF */