1 /* 2 * PROJECT: Win32 subsystem 3 * LICENSE: See COPYING in the top level directory 4 * FILE: win32ss/gdi/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 = 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 */ 544