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