[WIN32K]
[reactos.git] / reactos / win32ss / gdi / dib / dib24bpp.c
1 /*
2 * PROJECT: Win32 subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/dib/dib24bpp.c
5 * PURPOSE: Device Independant Bitmap functions, 24bpp
6 * PROGRAMMERS: Jason Filby
7 * Thomas Bluemel
8 * Gregor Anich
9 */
10
11 #include <win32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 VOID
17 DIB_24BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
18 {
19 PBYTE addr = (PBYTE)SurfObj->pvScan0 + (y * SurfObj->lDelta) + (x << 1) + x;
20 *(PUSHORT)(addr) = c & 0xFFFF;
21 *(addr + 2) = (c >> 16) & 0xFF;
22 }
23
24 ULONG
25 DIB_24BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
26 {
27 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + (x << 1) + x;
28 return *(PUSHORT)(addr) + (*(addr + 2) << 16);
29 }
30
31
32
33 VOID
34 DIB_24BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
35 {
36 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y1 * SurfObj->lDelta + (x << 1) + x;
37 LONG lDelta = SurfObj->lDelta;
38
39 c &= 0xFFFFFF;
40 while(y1++ < y2)
41 {
42 *(PUSHORT)(addr) = c & 0xFFFF;
43 *(addr + 2) = (BYTE)(c >> 16);
44
45 addr += lDelta;
46 }
47 }
48
49 BOOLEAN
50 DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
51 {
52 LONG i, j, sx, sy, xColor, f1;
53 PBYTE SourceBits, DestBits, SourceLine, DestLine;
54 PBYTE SourceBits_4BPP, SourceLine_4BPP;
55 PWORD SourceBits_16BPP, SourceLine_16BPP;
56
57 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left * 3;
58
59 switch(BltInfo->SourceSurface->iBitmapFormat)
60 {
61 case BMF_1BPP:
62 sx = BltInfo->SourcePoint.x;
63 sy = BltInfo->SourcePoint.y;
64
65 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
66 {
67 sx = BltInfo->SourcePoint.x;
68 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
69 {
70 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
71 {
72 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
73 } else {
74 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
75 }
76 sx++;
77 }
78 sy++;
79 }
80 break;
81
82 case BMF_4BPP:
83 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
84
85 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
86 {
87 SourceLine_4BPP = SourceBits_4BPP;
88 DestLine = DestBits;
89 sx = BltInfo->SourcePoint.x;
90 f1 = sx & 1;
91
92 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
93 {
94 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
95 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
96 *DestLine++ = xColor & 0xff;
97 *(PWORD)DestLine = (WORD)(xColor >> 8);
98 DestLine += 2;
99 if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
100 sx++;
101 }
102
103 SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
104 DestBits += BltInfo->DestSurface->lDelta;
105 }
106 break;
107
108 case BMF_8BPP:
109 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
110 DestLine = DestBits;
111
112 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
113 {
114 SourceBits = SourceLine;
115 DestBits = DestLine;
116
117 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
118 {
119 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits);
120 *DestBits = xColor & 0xff;
121 *(PWORD)(DestBits + 1) = (WORD)(xColor >> 8);
122 SourceBits += 1;
123 DestBits += 3;
124 }
125
126 SourceLine += BltInfo->SourceSurface->lDelta;
127 DestLine += BltInfo->DestSurface->lDelta;
128 }
129 break;
130
131 case BMF_16BPP:
132 SourceBits_16BPP = (PWORD)((PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x);
133
134 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
135 {
136 SourceLine_16BPP = SourceBits_16BPP;
137 DestLine = DestBits;
138
139 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
140 {
141 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceLine_16BPP);
142 *DestLine++ = xColor & 0xff;
143 *(PWORD)DestLine = (WORD)(xColor >> 8);
144 DestLine += 2;
145 SourceLine_16BPP++;
146 }
147
148 SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP + BltInfo->SourceSurface->lDelta);
149 DestBits += BltInfo->DestSurface->lDelta;
150 }
151 break;
152
153 case BMF_24BPP:
154 if (NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
155 {
156 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
157 {
158 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
159 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
160 {
161 RtlMoveMemory(DestBits, SourceBits, 3 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
162 SourceBits += BltInfo->SourceSurface->lDelta;
163 DestBits += BltInfo->DestSurface->lDelta;
164 }
165 }
166 else
167 {
168 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
169 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 3 * BltInfo->DestRect.left;
170 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
171 {
172 RtlMoveMemory(DestBits, SourceBits, 3 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
173 SourceBits -= BltInfo->SourceSurface->lDelta;
174 DestBits -= BltInfo->DestSurface->lDelta;
175 }
176 }
177 }
178 else
179 {
180 sx = BltInfo->SourcePoint.x;
181 sy = BltInfo->SourcePoint.y;
182
183 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
184 {
185 sx = BltInfo->SourcePoint.x;
186 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
187 {
188 DWORD pixel = DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy);
189 DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, pixel));
190 sx++;
191 }
192 sy++;
193 }
194 }
195 break;
196
197 case BMF_32BPP:
198 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
199 DestLine = DestBits;
200
201 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
202 {
203 SourceBits = SourceLine;
204 DestBits = DestLine;
205
206 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
207 {
208 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((PDWORD) SourceBits));
209 *DestBits = xColor & 0xff;
210 *(PWORD)(DestBits + 1) = (WORD)(xColor >> 8);
211 SourceBits += 4;
212 DestBits += 3;
213 }
214
215 SourceLine += BltInfo->SourceSurface->lDelta;
216 DestLine += BltInfo->DestSurface->lDelta;
217 }
218 break;
219
220 default:
221 DbgPrint("DIB_24BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
222 return FALSE;
223 }
224
225 return TRUE;
226 }
227
228 BOOLEAN
229 DIB_24BPP_BitBlt(PBLTINFO BltInfo)
230 {
231 LONG DestX, DestY;
232 LONG SourceX, SourceY;
233 LONG PatternY = 0;
234 ULONG Dest, Source = 0, Pattern = 0;
235 BOOL UsesSource;
236 BOOL UsesPattern;
237 PBYTE DestBits;
238
239 UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4);
240 UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4);
241
242 SourceY = BltInfo->SourcePoint.y;
243 DestBits = (PBYTE)(
244 (PBYTE)BltInfo->DestSurface->pvScan0 +
245 (BltInfo->DestRect.left << 1) + BltInfo->DestRect.left +
246 BltInfo->DestRect.top * BltInfo->DestSurface->lDelta);
247
248 if (UsesPattern)
249 {
250 if (BltInfo->PatternSurface)
251 {
252 PatternY = (BltInfo->DestRect.top - BltInfo->BrushOrigin.y) %
253 BltInfo->PatternSurface->sizlBitmap.cy;
254 }
255 else
256 {
257 if (BltInfo->Brush)
258 Pattern = BltInfo->Brush->iSolidColor;
259 }
260 }
261
262 for (DestY = BltInfo->DestRect.top; DestY < BltInfo->DestRect.bottom; DestY++)
263 {
264 SourceX = BltInfo->SourcePoint.x;
265
266 for (DestX = BltInfo->DestRect.left; DestX < BltInfo->DestRect.right; DestX++, DestBits += 3, SourceX++)
267 {
268 Dest = *((PUSHORT)DestBits) + (*(DestBits + 2) << 16);
269
270 if (UsesSource)
271 {
272 Source = DIB_GetSource(BltInfo->SourceSurface, SourceX, SourceY, BltInfo->XlateSourceToDest);
273 }
274
275 if (BltInfo->PatternSurface)
276 {
277 Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX - BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
278 }
279
280 Dest = DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xFFFFFF;
281 *(PUSHORT)(DestBits) = Dest & 0xFFFF;
282 *(DestBits + 2) = (BYTE)(Dest >> 16);
283 }
284
285 SourceY++;
286 if (BltInfo->PatternSurface)
287 {
288 PatternY++;
289 PatternY %= BltInfo->PatternSurface->sizlBitmap.cy;
290 }
291 DestBits -= (BltInfo->DestRect.right - BltInfo->DestRect.left) * 3;
292 DestBits += BltInfo->DestSurface->lDelta;
293 }
294
295 return TRUE;
296 }
297
298 /* BitBlt Optimize */
299 BOOLEAN
300 DIB_24BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
301 {
302 LONG DestY;
303
304 #if defined(_M_IX86) && !defined(_MSC_VER)
305 PBYTE xaddr = (PBYTE)DestSurface->pvScan0 + DestRect->top * DestSurface->lDelta + (DestRect->left << 1) + DestRect->left;
306 PBYTE addr;
307 ULONG Count;
308 ULONG xCount=DestRect->right - DestRect->left;
309
310 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
311 {
312 Count = xCount;
313 addr = xaddr;
314 xaddr = (PBYTE)((ULONG_PTR)addr + DestSurface->lDelta);
315
316 if (Count < 8)
317 {
318 /* For small fills, don't bother doing anything fancy */
319 while (Count--)
320 {
321 *(PUSHORT)(addr) = color;
322 addr += 2;
323 *(addr) = color >> 16;
324 addr += 1;
325 }
326 }
327 else
328 {
329 /* Align to 4-byte address */
330 while (0 != ((ULONG_PTR) addr & 0x3))
331 {
332 *(PUSHORT)(addr) = color;
333 addr += 2;
334 *(addr) = color >> 16;
335 addr += 1;
336 Count--;
337 }
338 /* If the color we need to fill with is 0ABC, then the final mem pattern
339 * (note little-endianness) would be:
340 *
341 * |C.B.A|C.B.A|C.B.A|C.B.A| <- pixel borders
342 * |C.B.A.C|B.A.C.B|A.C.B.A| <- ULONG borders
343 *
344 * So, taking endianness into account again, we need to fill with these
345 * ULONGs: CABC BCAB ABCA */
346
347 /* This is about 30% faster than the generic C code below */
348 __asm__ __volatile__ (
349 "movl %1, %%ecx\n\t"
350 "andl $0xffffff, %%ecx\n\t" /* 0ABC */
351 "movl %%ecx, %%ebx\n\t" /* Construct BCAB in ebx */
352 "shrl $8, %%ebx\n\t"
353 "movl %%ecx, %%eax\n\t"
354 "shll $16, %%eax\n\t"
355 "orl %%eax, %%ebx\n\t"
356 "movl %%ecx, %%edx\n\t" /* Construct ABCA in edx */
357 "shll $8, %%edx\n\t"
358 "movl %%ecx, %%eax\n\t"
359 "shrl $16, %%eax\n\t"
360 "orl %%eax, %%edx\n\t"
361 "movl %%ecx, %%eax\n\t" /* Construct CABC in eax */
362 "shll $24, %%eax\n\t"
363 "orl %%ecx, %%eax\n\t"
364 "movl %2, %%ecx\n\t" /* Load count */
365 "shr $2, %%ecx\n\t"
366 "movl %3, %%edi\n" /* Load dest */
367 "1:\n\t"
368 "movl %%eax, (%%edi)\n\t" /* Store 4 pixels, 12 bytes */
369 "movl %%ebx, 4(%%edi)\n\t"
370 "movl %%edx, 8(%%edi)\n\t"
371 "addl $12, %%edi\n\t"
372 "dec %%ecx\n\t"
373 "jnz 1b\n\t"
374 "movl %%edi, %0"
375 : "=m"(addr)
376 : "m"(color), "m"(Count), "m"(addr)
377 : "%eax", "%ebx", "%ecx", "%edx", "%edi");
378 Count = Count & 0x03;
379 while (0 != Count--)
380 {
381 *(PUSHORT)(addr) = color;
382 addr += 2;
383 *(addr) = color >> 16;
384 addr += 1;
385 }
386 }
387 }
388 #else
389
390 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
391 {
392 DIB_24BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
393 }
394 #endif
395 return TRUE;
396 }
397
398 BOOLEAN
399 DIB_24BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
400 RECTL* DestRect, RECTL *SourceRect,
401 XLATEOBJ *ColorTranslation, ULONG iTransColor)
402 {
403 LONG X, Y, SourceX, SourceY = 0, wd;
404 ULONG Source = 0, Dest;
405 BYTE *DestBits;
406
407 LONG DstHeight;
408 LONG DstWidth;
409 LONG SrcHeight;
410 LONG SrcWidth;
411
412 DstHeight = DestRect->bottom - DestRect->top;
413 DstWidth = DestRect->right - DestRect->left;
414 SrcHeight = SourceRect->bottom - SourceRect->top;
415 SrcWidth = SourceRect->right - SourceRect->left;
416
417 DestBits = (BYTE*)((PBYTE)DestSurf->pvScan0 +
418 (DestRect->left * 3) +
419 DestRect->top * DestSurf->lDelta);
420 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) * 3);
421
422 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
423 {
424 SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
425 for(X = DestRect->left; X < DestRect->right; X++, DestBits += 3)
426 {
427 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
428 if (SourceX >= 0 && SourceY >= 0 &&
429 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
430 {
431 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
432 if(Source != iTransColor)
433 {
434 Dest = (BYTE)XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFFFF;
435 *(PUSHORT)(DestBits) = Dest & 0xFFFF;
436 *(DestBits + 2) = (BYTE)(Dest >> 16);
437 }
438 }
439 }
440
441 DestBits = (BYTE*)((ULONG_PTR)DestBits + wd);
442 }
443
444 return TRUE;
445 }
446
447 typedef union {
448 ULONG ul;
449 struct {
450 UCHAR red;
451 UCHAR green;
452 UCHAR blue;
453 UCHAR alpha;
454 } col;
455 } NICEPIXEL32;
456
457 static __inline UCHAR
458 Clamp8(ULONG val)
459 {
460 return (val > 255) ? 255 : (UCHAR)val;
461 }
462
463 BOOLEAN
464 DIB_24BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
465 RECTL* SourceRect, CLIPOBJ* ClipRegion,
466 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
467 {
468 INT Rows, Cols, SrcX, SrcY;
469 register PUCHAR Dst;
470 BLENDFUNCTION BlendFunc;
471 register NICEPIXEL32 DstPixel, SrcPixel;
472 UCHAR Alpha;
473 //UCHAR SrcBpp;
474
475 DPRINT("DIB_24BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
476 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
477 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
478
479 BlendFunc = BlendObj->BlendFunction;
480 if (BlendFunc.BlendOp != AC_SRC_OVER)
481 {
482 DPRINT1("BlendOp != AC_SRC_OVER\n");
483 return FALSE;
484 }
485 if (BlendFunc.BlendFlags != 0)
486 {
487 DPRINT1("BlendFlags != 0\n");
488 return FALSE;
489 }
490 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
491 {
492 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
493 return FALSE;
494 }
495 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
496 BitsPerFormat(Source->iBitmapFormat) != 32)
497 {
498 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
499 return FALSE;
500 }
501
502 Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
503 (DestRect->left * 3));
504 //SrcBpp = BitsPerFormat(Source->iBitmapFormat);
505
506 Rows = 0;
507 SrcY = SourceRect->top;
508 while (++Rows <= DestRect->bottom - DestRect->top)
509 {
510 Cols = 0;
511 SrcX = SourceRect->left;
512 while (++Cols <= DestRect->right - DestRect->left)
513 {
514 SrcPixel.ul = DIB_GetSource(Source, SrcX, SrcY, ColorTranslation);
515 SrcPixel.col.red = (SrcPixel.col.red * BlendFunc.SourceConstantAlpha) / 255;
516 SrcPixel.col.green = (SrcPixel.col.green * BlendFunc.SourceConstantAlpha) / 255;
517 SrcPixel.col.blue = (SrcPixel.col.blue * BlendFunc.SourceConstantAlpha) / 255;
518 if (!(BlendFunc.AlphaFormat & AC_SRC_ALPHA))
519 {
520 Alpha = BlendFunc.SourceConstantAlpha ;
521 }
522 else
523 {
524 Alpha = (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha) / 255;
525 }
526
527 DstPixel.col.red = Clamp8((*Dst * (255 - Alpha)) / 255 + SrcPixel.col.red) ;
528 DstPixel.col.green = Clamp8((*(Dst+1) * (255 - Alpha) / 255 + SrcPixel.col.green)) ;
529 DstPixel.col.blue = Clamp8((*(Dst+2) * (255 - Alpha)) / 255 + SrcPixel.col.blue) ;
530 *Dst++ = DstPixel.col.red;
531 *Dst++ = DstPixel.col.green;
532 *Dst++ = DstPixel.col.blue;
533 SrcX = SourceRect->left + (Cols*(SourceRect->right - SourceRect->left))/(DestRect->right - DestRect->left);
534 }
535 Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + ((DestRect->top + Rows) * Dest->lDelta) +
536 (DestRect->left*3));
537 SrcY = SourceRect->top + (Rows*(SourceRect->bottom - SourceRect->top))/(DestRect->bottom - DestRect->top);
538 }
539
540 return TRUE;
541 }
542
543 /* EOF */