1 /* 2 * PROJECT: Win32 subsystem 3 * LICENSE: See COPYING in the top level directory 4 * FILE: win32ss/gdi/dib/dib16bpp.c 5 * PURPOSE: Device Independant Bitmap functions, 16bpp 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_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c) 22 { 23 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta; 24 PWORD addr = (PWORD)byteaddr + x; 25 26 *addr = (WORD)c; 27 } 28 29 ULONG 30 DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y) 31 { 32 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta; 33 PWORD addr = (PWORD)byteaddr + x; 34 return (ULONG)(*addr); 35 } 36 37 VOID 38 DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c) 39 { 40 PDWORD addr = (PDWORD)((PWORD)((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta) + x1); 41 42 #if defined(_M_IX86) && !defined(_MSC_VER) 43 /* This is about 10% faster than the generic C code below */ 44 LONG Count = x2 - x1; 45 46 __asm__ __volatile__ ( 47 " cld\n" 48 " mov %0, %%eax\n" 49 " shl $16, %%eax\n" 50 " andl $0xffff, %0\n" /* If the pixel value is "abcd", put "abcdabcd" in %eax */ 51 " or %0, %%eax\n" 52 " mov %2, %%edi\n" 53 " test $0x03, %%edi\n" /* Align to fullword boundary */ 54 " jz 0f\n" 55 " stosw\n" 56 " dec %1\n" 57 " jz 1f\n" 58 "0:\n" 59 " mov %1,%%ecx\n" /* Setup count of fullwords to fill */ 60 " shr $1,%%ecx\n" 61 " rep stosl\n" /* The actual fill */ 62 " test $0x01, %1\n" /* One left to do at the right side? */ 63 " jz 1f\n" 64 " stosw\n" 65 "1:\n" 66 : /* no output */ 67 : "r"(c), "r"(Count), "m"(addr) 68 : "%eax", "%ecx", "%edi"); 69 #else /* _M_IX86 */ 70 LONG cx = x1; 71 DWORD cc; 72 73 if (0 != (cx & 0x01)) 74 { 75 *((PWORD) addr) = (WORD)c; 76 cx++; 77 addr = (PDWORD)((PWORD)(addr) + 1); 78 } 79 cc = ((c & 0xffff) << 16) | (c & 0xffff); 80 while(cx + 1 < x2) 81 { 82 *addr++ = cc; 83 cx += 2; 84 } 85 if (cx < x2) 86 { 87 *((PWORD) addr) = (WORD)c; 88 } 89 #endif /* _M_IX86 */ 90 } 91 92 93 VOID 94 DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c) 95 { 96 #if defined(_M_IX86) && !defined(_MSC_VER) 97 asm volatile( 98 " testl %2, %2" "\n\t" 99 " jle 2f" "\n\t" 100 " movl %2, %%ecx" "\n\t" 101 " shrl $2, %2" "\n\t" 102 " andl $3, %%ecx" "\n\t" 103 " jz 1f" "\n\t" 104 "0:" "\n\t" 105 " movw %%ax, (%0)" "\n\t" 106 " addl %1, %0" "\n\t" 107 " decl %%ecx" "\n\t" 108 " jnz 0b" "\n\t" 109 " testl %2, %2" "\n\t" 110 " jz 2f" "\n\t" 111 "1:" "\n\t" 112 " movw %%ax, (%0)" "\n\t" 113 " addl %1, %0" "\n\t" 114 " movw %%ax, (%0)" "\n\t" 115 " addl %1, %0" "\n\t" 116 " movw %%ax, (%0)" "\n\t" 117 " addl %1, %0" "\n\t" 118 " movw %%ax, (%0)" "\n\t" 119 " addl %1, %0" "\n\t" 120 " decl %2" "\n\t" 121 " jnz 1b" "\n\t" 122 "2:" "\n\t" 123 : /* no output */ 124 : "r"((PBYTE)SurfObj->pvScan0 + (y1 * SurfObj->lDelta) + (x * sizeof (WORD))), 125 "r"(SurfObj->lDelta), "r"(y2 - y1), "a"(c) 126 : "cc", "memory", "%ecx"); 127 #else 128 PBYTE byteaddr = (PBYTE)(ULONG_PTR)SurfObj->pvScan0 + y1 * SurfObj->lDelta; 129 PWORD addr = (PWORD)byteaddr + x; 130 LONG lDelta = SurfObj->lDelta; 131 132 byteaddr = (PBYTE)addr; 133 while(y1++ < y2) 134 { 135 *addr = (WORD)c; 136 137 byteaddr += lDelta; 138 addr = (PWORD)byteaddr; 139 } 140 #endif 141 } 142 143 BOOLEAN 144 DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) 145 { 146 LONG i, j, sx, sy, xColor, f1; 147 PBYTE SourceBits, DestBits, SourceLine, DestLine; 148 PBYTE SourceBits_4BPP, SourceLine_4BPP; 149 PWORD Source32, Dest32; 150 DWORD Index, StartLeft, EndRight; 151 BOOLEAN bTopToBottom, bLeftToRight; 152 153 DPRINT("DIB_16BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n", 154 BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy, 155 BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy, 156 BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom); 157 158 /* Get back left to right flip here */ 159 bLeftToRight = BltInfo->DestRect.left > BltInfo->DestRect.right; 160 161 /* Check for top to bottom flip needed. */ 162 bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom; 163 164 DPRINT("BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n", 165 BltInfo->SourcePoint.x, BltInfo->SourcePoint.y); 166 167 /* Make WellOrdered with top < bottom and left < right */ 168 RECTL_vMakeWellOrdered(&BltInfo->DestRect); 169 170 DPRINT("BPP is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n", 171 BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y); 172 173 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left; 174 175 switch(BltInfo->SourceSurface->iBitmapFormat) 176 { 177 case BMF_1BPP: 178 DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n", 179 BltInfo->DestRect.right - BltInfo->DestRect.left); 180 sx = BltInfo->SourcePoint.x; 181 182 /* This sets sy to the top line */ 183 sy = BltInfo->SourcePoint.y; 184 185 if (bTopToBottom) 186 { 187 /* This sets sy to the bottom line */ 188 sy += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1); 189 } 190 191 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++) 192 { 193 sx = BltInfo->SourcePoint.x; 194 195 if (bLeftToRight) 196 { 197 /* This sets the sx to the rightmost pixel */ 198 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1); 199 StartLeft = BltInfo->DestRect.left + 1; 200 EndRight = BltInfo->DestRect.right + 1; 201 } 202 else 203 { 204 StartLeft = BltInfo->DestRect.left; 205 EndRight = BltInfo->DestRect.right; 206 } 207 208 for (i = StartLeft; i < EndRight; i++) 209 { 210 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0) 211 { 212 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, 213 XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0)); 214 } 215 else 216 { 217 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, 218 XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1)); 219 } 220 DEC_OR_INC(sx, bLeftToRight, 1); 221 } 222 DEC_OR_INC(sy, bTopToBottom, 1); 223 } 224 break; 225 226 case BMF_4BPP: 227 DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n", 228 BltInfo->DestRect.right - BltInfo->DestRect.left); 229 230 /* This sets SourceBits_4BPP to the top line */ 231 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + 232 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 233 (BltInfo->SourcePoint.x >> 1); 234 235 if (bTopToBottom) 236 { 237 /* This sets SourceBits_4BPP to the bottom line */ 238 SourceBits_4BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta; 239 } 240 241 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++) 242 { 243 SourceLine_4BPP = SourceBits_4BPP; 244 sx = BltInfo->SourcePoint.x; 245 if (bLeftToRight) 246 { 247 /* This sets sx to the rightmost pixel */ 248 sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1); 249 } 250 251 f1 = sx & 1; 252 253 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++) 254 { 255 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 256 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1))); 257 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor); 258 if(f1 == 1) 259 { 260 DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1); 261 f1 = 0; 262 } 263 else 264 { 265 f1 = 1; 266 } 267 DEC_OR_INC(sx, bLeftToRight, 1); 268 } 269 DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta); 270 } 271 break; 272 273 case BMF_8BPP: 274 DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n", 275 BltInfo->DestRect.right - BltInfo->DestRect.left); 276 277 /* This sets SourceLine to the top line */ 278 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + 279 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 280 BltInfo->SourcePoint.x; 281 DestLine = DestBits; 282 283 if (bTopToBottom) 284 { 285 /* This sets SourceLine to the bottom line */ 286 SourceLine += BltInfo->SourceSurface->lDelta 287 * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1); 288 } 289 290 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) 291 { 292 SourceBits = SourceLine; 293 DestBits = DestLine; 294 295 if (bLeftToRight) 296 { 297 /* This sets SourceBits to the rightmost pixel */ 298 SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1); 299 } 300 301 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++) 302 { 303 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( 304 BltInfo->XlateSourceToDest, *SourceBits); 305 DEC_OR_INC(SourceBits, bLeftToRight, 1); 306 DestBits += 2; 307 } 308 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta); 309 DestLine += BltInfo->DestSurface->lDelta; 310 } 311 break; 312 313 case BMF_16BPP: 314 DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n", 315 BltInfo->DestRect.right - BltInfo->DestRect.left); 316 317 DPRINT("BMF_16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 318 BltInfo->DestRect.left, BltInfo->DestRect.top, 319 BltInfo->DestRect.right, BltInfo->DestRect.bottom, 320 BltInfo->DestRect.right - BltInfo->DestRect.left); 321 322 if ((BltInfo->XlateSourceToDest == NULL || 323 (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) && 324 (!bTopToBottom && !bLeftToRight)) 325 { 326 DPRINT("XO_TRIVIAL is TRUE.\n"); 327 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y) 328 { 329 /* This sets SourceBits to the top line */ 330 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + 331 (BltInfo->SourcePoint.y * 332 BltInfo->SourceSurface->lDelta) + 2 * 333 BltInfo->SourcePoint.x; 334 335 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) 336 { 337 RtlMoveMemory(DestBits, SourceBits, 338 2 * (BltInfo->DestRect.right - 339 BltInfo->DestRect.left)); 340 341 SourceBits += BltInfo->SourceSurface->lDelta; 342 DestBits += BltInfo->DestSurface->lDelta; 343 } 344 } 345 else 346 { 347 /* This sets SourceBits to the bottom line */ 348 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + 349 ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - 350 BltInfo->DestRect.top - 1) * 351 BltInfo->SourceSurface->lDelta) + 2 * 352 BltInfo->SourcePoint.x; 353 354 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + 355 ((BltInfo->DestRect.bottom - 1) * 356 BltInfo->DestSurface->lDelta) + 2 * 357 BltInfo->DestRect.left; 358 359 for (j = BltInfo->DestRect.bottom - 1; 360 BltInfo->DestRect.top <= j; j--) 361 { 362 RtlMoveMemory(DestBits, SourceBits, 2 * 363 (BltInfo->DestRect.right - 364 BltInfo->DestRect.left)); 365 366 SourceBits -= BltInfo->SourceSurface->lDelta; 367 DestBits -= BltInfo->DestSurface->lDelta; 368 } 369 } 370 } 371 else 372 { 373 DPRINT("XO_TRIVIAL is NOT TRUE.\n"); 374 if (!bTopToBottom && !bLeftToRight) 375 /* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */ 376 { 377 DPRINT("Flip is None.\n"); 378 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y) 379 { 380 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + 381 (BltInfo->SourcePoint.y * 382 BltInfo->SourceSurface->lDelta) + 2 * 383 BltInfo->SourcePoint.x; 384 385 DestLine = DestBits; 386 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) 387 { 388 SourceBits = SourceLine; 389 DestBits = DestLine; 390 for (i = BltInfo->DestRect.left; i < 391 BltInfo->DestRect.right; i++) 392 { 393 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( 394 BltInfo->XlateSourceToDest, 395 *((WORD *)SourceBits)); 396 SourceBits += 2; 397 DestBits += 2; 398 } 399 SourceLine += BltInfo->SourceSurface->lDelta; 400 DestLine += BltInfo->DestSurface->lDelta; 401 } 402 } 403 else 404 { 405 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + 406 ((BltInfo->SourcePoint.y + 407 BltInfo->DestRect.bottom - 408 BltInfo->DestRect.top - 1) * 409 BltInfo->SourceSurface->lDelta) + 2 * 410 BltInfo->SourcePoint.x; 411 412 DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 + 413 ((BltInfo->DestRect.bottom - 1) * 414 BltInfo->DestSurface->lDelta) + 2 * 415 BltInfo->DestRect.left; 416 417 for (j = BltInfo->DestRect.bottom - 1; 418 BltInfo->DestRect.top <= j; j--) 419 { 420 SourceBits = SourceLine; 421 DestBits = DestLine; 422 for (i = BltInfo->DestRect.left; i < 423 BltInfo->DestRect.right; i++) 424 { 425 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( 426 BltInfo->XlateSourceToDest, 427 *((WORD *)SourceBits)); 428 SourceBits += 2; 429 DestBits += 2; 430 } 431 SourceLine -= BltInfo->SourceSurface->lDelta; 432 DestLine -= BltInfo->DestSurface->lDelta; 433 } 434 } 435 } 436 else 437 { 438 /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */ 439 BOOL TopToBottomDone = FALSE; 440 441 if (bLeftToRight) 442 { 443 DPRINT("Flip is bLeftToRight.\n"); 444 445 /* Allocate enough pixels for a row in WORD's */ 446 WORD *store = ExAllocatePoolWithTag(NonPagedPool, 447 (BltInfo->DestRect.right - BltInfo->DestRect.left + 1) * 2, TAG_DIB); 448 if (store == NULL) 449 { 450 DPRINT1("Storage Allocation Failed.\n"); 451 return FALSE; 452 } 453 WORD Index; 454 455 /* This sets SourceBits to the bottom line */ 456 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 457 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) 458 * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x; 459 460 /* Sets DestBits to the bottom line */ 461 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 462 + (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta 463 + 2 * BltInfo->DestRect.left + 2; 464 465 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--) 466 { 467 /* Set Dest32 to right pixel */ 468 Dest32 = (WORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1); 469 Source32 = (WORD *) SourceBits; 470 471 Index = 0; 472 473 /* Store pixels from left to right */ 474 for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--) 475 { 476 store[Index] = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *(WORD *)Source32++); 477 Index++; 478 } 479 480 Index = 0; 481 482 /* Copy stored data to pixels from right to left */ 483 for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--) 484 { 485 *(WORD *)Dest32-- = store[Index]; 486 Index++; 487 } 488 489 SourceBits -= BltInfo->SourceSurface->lDelta; 490 DestBits -= BltInfo->DestSurface->lDelta; 491 } 492 ExFreePoolWithTag(store, TAG_DIB); 493 TopToBottomDone = TRUE; 494 } 495 496 if (bTopToBottom) 497 { 498 DPRINT("Flip is bTopToBottom.\n"); 499 500 /* Allocate enough pixels for a column in WORD's */ 501 WORD *store = ExAllocatePoolWithTag(NonPagedPool, 502 (BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1) * 2, TAG_DIB); 503 if (store == NULL) 504 { 505 DPRINT1("Storage Allocation Failed.\n"); 506 return FALSE; 507 } 508 509 /* This set SourceBits to the top line */ 510 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 511 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) 512 + 2 * BltInfo->SourcePoint.x; 513 514 /* This sets DestBits to the top line */ 515 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 516 + ((BltInfo->DestRect.top) * BltInfo->DestSurface->lDelta) 517 + 2 * BltInfo->DestRect.left; 518 519 if ((BltInfo->SourceSurface->fjBitmap & BMF_TOPDOWN) == 0) 520 { 521 DestBits += BltInfo->DestSurface->lDelta; 522 } 523 524 if (bLeftToRight) 525 { 526 DPRINT("Adjusting DestBits for bLeftToRight.\n"); 527 DestBits += 2; 528 } 529 530 /* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight 531 * and have already completed the bLeftToRight. So we will lose our first flip output 532 * unless we work with its output which is at the destination site. So in this case 533 * our new Source becomes the previous outputs Destination. */ 534 535 if (TopToBottomDone) 536 { 537 /* This sets SourceBits to the top line */ 538 SourceBits = DestBits; 539 } 540 541 for (j = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= j ; j--) 542 { 543 /* Set Dest32 to bottom pixel */ 544 Dest32 = (WORD *) DestBits + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) 545 * BltInfo->DestSurface->lDelta / 2; 546 Source32 = (WORD *) SourceBits; 547 548 Index = 0; 549 550 /* Store pixels from top to bottom */ 551 for (i = BltInfo->DestRect.top; i <= BltInfo->DestRect.bottom - 1; i++) 552 { 553 store[Index] = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32); 554 Source32 += BltInfo->SourceSurface->lDelta / 2; 555 Index++; 556 } 557 558 Index = 0; 559 560 /* Copy stored data to pixels from bottom to top */ 561 for (i = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= i; i--) 562 { 563 *Dest32 = store[Index]; 564 Dest32 -= BltInfo->DestSurface->lDelta / 2; 565 Index++; 566 } 567 SourceBits += 2; 568 DestBits += 2; 569 } 570 ExFreePoolWithTag(store, TAG_DIB); 571 } 572 573 } 574 } 575 break; 576 577 case BMF_24BPP: 578 579 DPRINT("BMF_24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n", 580 BltInfo->DestRect.left, BltInfo->DestRect.top, 581 BltInfo->DestRect.right, BltInfo->DestRect.bottom, 582 BltInfo->DestRect.right - BltInfo->DestRect.left); 583 584 /* This sets SourceLine to the top line */ 585 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + 586 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 587 3 * BltInfo->SourcePoint.x; 588 589 if (bTopToBottom) 590 { 591 /* This sets SourceLine to the bottom line */ 592 SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1); 593 } 594 DestLine = DestBits; 595 596 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) 597 { 598 SourceBits = SourceLine; 599 DestBits = DestLine; 600 601 if (bLeftToRight) 602 { 603 /* This sets the SourceBits to the rightmost pixel */ 604 SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 3; 605 } 606 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++) 607 { 608 xColor = (*(SourceBits + 2) << 0x10) + 609 (*(SourceBits + 1) << 0x08) + (*(SourceBits)); 610 611 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( 612 BltInfo->XlateSourceToDest, xColor); 613 614 DEC_OR_INC(SourceBits, bLeftToRight, 3); 615 DestBits += 2; 616 } 617 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta); 618 DestLine += BltInfo->DestSurface->lDelta; 619 } 620 break; 621 622 case BMF_32BPP: 623 DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n", 624 BltInfo->DestRect.right - BltInfo->DestRect.left); 625 626 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + 627 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 628 4 * BltInfo->SourcePoint.x; 629 630 if (bTopToBottom) 631 { 632 /* This sets SourceLine to the bottom line */ 633 SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1; 634 } 635 DestLine = DestBits; 636 637 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) 638 { 639 SourceBits = SourceLine; 640 DestBits = DestLine; 641 642 if (bLeftToRight) 643 { 644 /* This sets SourceBits to the rightmost pixel */ 645 SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4; 646 } 647 648 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++) 649 { 650 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( 651 BltInfo->XlateSourceToDest, 652 *((PDWORD) SourceBits)); 653 DEC_OR_INC(SourceBits, bLeftToRight, 4); 654 DestBits += 2; 655 } 656 657 DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta); 658 DestLine += BltInfo->DestSurface->lDelta; 659 } 660 break; 661 662 default: 663 DPRINT1("DIB_16BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n", 664 BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat)); 665 return FALSE; 666 } 667 668 return TRUE; 669 } 670 671 /* Optimize for bitBlt */ 672 BOOLEAN 673 DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color) 674 { 675 LONG DestY; 676 677 /* Make WellOrdered with top < bottom and left < right */ 678 RECTL_vMakeWellOrdered(DestRect); 679 680 #if defined(_M_IX86) && !defined(_MSC_VER) 681 /* This is about 10% faster than the generic C code below */ 682 ULONG delta = DestSurface->lDelta; 683 ULONG width = (DestRect->right - DestRect->left) ; 684 PULONG pos = (PULONG) ((PBYTE)DestSurface->pvScan0 + DestRect->top * delta + (DestRect->left<<1)); 685 color = (color&0xffff); /* If the color value is "abcd", put "abcdabcd" into color */ 686 color += (color<<16); 687 688 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++) 689 { 690 __asm__ __volatile__ ( 691 "cld\n\t" 692 "mov %1,%%ebx\n\t" 693 "mov %2,%%edi\n\t" 694 "test $0x03, %%edi\n\t" /* Align to fullword boundary */ 695 "jz 1f\n\t" 696 "stosw\n\t" 697 "dec %%ebx\n\t" 698 "jz 2f\n" 699 "1:\n\t" 700 "mov %%ebx,%%ecx\n\t" /* Setup count of fullwords to fill */ 701 "shr $1,%%ecx\n\t" 702 "rep stosl\n\t" /* The actual fill */ 703 "test $0x01, %%ebx\n\t" /* One left to do at the right side? */ 704 "jz 2f\n\t" 705 "stosw\n" 706 "2:" 707 : 708 : "a" (color), "r" (width), "m" (pos) 709 : "%ecx", "%ebx", "%edi"); 710 pos =(PULONG)((ULONG_PTR)pos + delta); 711 } 712 #else /* _M_IX86 */ 713 714 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++) 715 { 716 DIB_16BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color); 717 } 718 #endif 719 return TRUE; 720 } 721 722 BOOLEAN 723 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, 724 RECTL* DestRect, RECTL *SourceRect, 725 XLATEOBJ *ColorTranslation, ULONG iTransColor) 726 { 727 LONG RoundedRight, X, Y, SourceX = 0, SourceY = 0, wd; 728 ULONG *DestBits, Source, Dest; 729 730 LONG DstHeight; 731 LONG DstWidth; 732 LONG SrcHeight; 733 LONG SrcWidth; 734 735 DstHeight = DestRect->bottom - DestRect->top; 736 DstWidth = DestRect->right - DestRect->left; 737 SrcHeight = SourceRect->bottom - SourceRect->top; 738 SrcWidth = SourceRect->right - SourceRect->left; 739 740 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1); 741 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 + 742 (DestRect->left << 1) + 743 DestRect->top * DestSurf->lDelta); 744 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1); 745 746 for(Y = DestRect->top; Y < DestRect->bottom; Y++) 747 { 748 SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight; 749 for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2) 750 { 751 Dest = *DestBits; 752 753 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth; 754 if (SourceX >= 0 && SourceY >= 0 && 755 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY) 756 { 757 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY); 758 if(Source != iTransColor) 759 { 760 Dest &= 0xFFFF0000; 761 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF); 762 } 763 } 764 765 SourceX = SourceRect->left+(X+1 - DestRect->left) * SrcWidth / DstWidth; 766 if (SourceX >= 0 && SourceY >= 0 && 767 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY) 768 { 769 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY); 770 if(Source != iTransColor) 771 { 772 Dest &= 0xFFFF; 773 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16); 774 } 775 } 776 777 *DestBits = Dest; 778 } 779 780 if(X < DestRect->right) 781 { 782 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth; 783 if (SourceX >= 0 && SourceY >= 0 && 784 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY) 785 { 786 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY); 787 if(Source != iTransColor) 788 { 789 *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation, 790 Source); 791 } 792 } 793 794 DestBits = (PULONG)((ULONG_PTR)DestBits + 2); 795 } 796 797 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd); 798 } 799 800 return TRUE; 801 } 802 803 typedef union 804 { 805 ULONG ul; 806 struct 807 { 808 UCHAR red; 809 UCHAR green; 810 UCHAR blue; 811 UCHAR alpha; 812 } col; 813 } NICEPIXEL32; 814 815 typedef union 816 { 817 USHORT us; 818 struct 819 { 820 USHORT blue :5; 821 USHORT green :6; 822 USHORT red :5; 823 } col; 824 } NICEPIXEL16_565; 825 826 typedef union 827 { 828 USHORT us; 829 struct 830 { 831 USHORT blue :5; 832 USHORT green :5; 833 USHORT red :5; 834 USHORT xxxx :1; 835 } col; 836 } NICEPIXEL16_555; 837 838 static __inline UCHAR 839 Clamp6(ULONG val) 840 { 841 return (val > 63) ? 63 : (UCHAR)val; 842 } 843 844 static __inline UCHAR 845 Clamp5(ULONG val) 846 { 847 return (val > 31) ? 31 : (UCHAR)val; 848 } 849 850 BOOLEAN 851 DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect, 852 RECTL* SourceRect, CLIPOBJ* ClipRegion, 853 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj) 854 { 855 INT DstX, DstY, SrcX, SrcY; 856 BLENDFUNCTION BlendFunc; 857 NICEPIXEL32 SrcPixel32; 858 UCHAR Alpha; 859 EXLATEOBJ* pexlo; 860 EXLATEOBJ exloSrcRGB; 861 862 DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n", 863 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom, 864 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); 865 866 BlendFunc = BlendObj->BlendFunction; 867 if (BlendFunc.BlendOp != AC_SRC_OVER) 868 { 869 DPRINT1("BlendOp != AC_SRC_OVER\n"); 870 return FALSE; 871 } 872 if (BlendFunc.BlendFlags != 0) 873 { 874 DPRINT1("BlendFlags != 0\n"); 875 return FALSE; 876 } 877 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0) 878 { 879 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat); 880 return FALSE; 881 } 882 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 && 883 (BitsPerFormat(Source->iBitmapFormat) != 32)) 884 { 885 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n"); 886 return FALSE; 887 } 888 889 if (!ColorTranslation) 890 { 891 DPRINT1("ColorTranslation must not be NULL!\n"); 892 return FALSE; 893 } 894 895 pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo); 896 EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0); 897 898 if (pexlo->ppalDst->flFlags & PAL_RGB16_555) 899 { 900 NICEPIXEL16_555 DstPixel16; 901 902 SrcY = SourceRect->top; 903 DstY = DestRect->top; 904 while ( DstY < DestRect->bottom ) 905 { 906 SrcX = SourceRect->left; 907 DstX = DestRect->left; 908 while(DstX < DestRect->right) 909 { 910 SrcPixel32.ul = DIB_GetSource(Source, SrcX, SrcY, &exloSrcRGB.xlo); 911 SrcPixel32.col.red = (SrcPixel32.col.red * BlendFunc.SourceConstantAlpha) / 255; 912 SrcPixel32.col.green = (SrcPixel32.col.green * BlendFunc.SourceConstantAlpha) / 255; 913 SrcPixel32.col.blue = (SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha) / 255; 914 915 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ? 916 (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha) / 255 : 917 BlendFunc.SourceConstantAlpha; 918 919 Alpha >>= 3; 920 921 DstPixel16.us = DIB_16BPP_GetPixel(Dest, DstX, DstY) & 0xFFFF; 922 /* Perform bit loss */ 923 SrcPixel32.col.red >>= 3; 924 SrcPixel32.col.green >>= 3; 925 SrcPixel32.col.blue >>= 3; 926 927 /* Do the blend in the right bit depth */ 928 DstPixel16.col.red = Clamp5((DstPixel16.col.red * (31 - Alpha)) / 31 + SrcPixel32.col.red); 929 DstPixel16.col.green = Clamp5((DstPixel16.col.green * (31 - Alpha)) / 31 + SrcPixel32.col.green); 930 DstPixel16.col.blue = Clamp5((DstPixel16.col.blue * (31 - Alpha)) / 31 + SrcPixel32.col.blue); 931 932 DIB_16BPP_PutPixel(Dest, DstX, DstY, DstPixel16.us); 933 934 DstX++; 935 SrcX = SourceRect->left + ((DstX-DestRect->left)*(SourceRect->right - SourceRect->left)) 936 /(DestRect->right-DestRect->left); 937 } 938 DstY++; 939 SrcY = SourceRect->top + ((DstY-DestRect->top)*(SourceRect->bottom - SourceRect->top)) 940 /(DestRect->bottom-DestRect->top); 941 } 942 } 943 else 944 { 945 NICEPIXEL16_565 DstPixel16; 946 UCHAR Alpha6, Alpha5; 947 948 SrcY = SourceRect->top; 949 DstY = DestRect->top; 950 while ( DstY < DestRect->bottom ) 951 { 952 SrcX = SourceRect->left; 953 DstX = DestRect->left; 954 while(DstX < DestRect->right) 955 { 956 SrcPixel32.ul = DIB_GetSource(Source, SrcX, SrcY, &exloSrcRGB.xlo); 957 SrcPixel32.col.red = (SrcPixel32.col.red * BlendFunc.SourceConstantAlpha) / 255; 958 SrcPixel32.col.green = (SrcPixel32.col.green * BlendFunc.SourceConstantAlpha) / 255; 959 SrcPixel32.col.blue = (SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha) / 255; 960 961 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ? 962 (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha) / 255 : 963 BlendFunc.SourceConstantAlpha; 964 965 Alpha6 = Alpha >> 2; 966 Alpha5 = Alpha >> 3; 967 968 DstPixel16.us = DIB_16BPP_GetPixel(Dest, DstX, DstY) & 0xFFFF; 969 /* Perform bit loss */ 970 SrcPixel32.col.red >>= 3; 971 SrcPixel32.col.green >>= 2; 972 SrcPixel32.col.blue >>= 3; 973 974 /* Do the blend in the right bit depth */ 975 DstPixel16.col.red = Clamp5((DstPixel16.col.red * (31 - Alpha5)) / 31 + SrcPixel32.col.red); 976 DstPixel16.col.green = Clamp6((DstPixel16.col.green * (63 - Alpha6)) / 63 + SrcPixel32.col.green); 977 DstPixel16.col.blue = Clamp5((DstPixel16.col.blue * (31 - Alpha5)) / 31 + SrcPixel32.col.blue); 978 979 DIB_16BPP_PutPixel(Dest, DstX, DstY, DstPixel16.us); 980 981 DstX++; 982 SrcX = SourceRect->left + ((DstX-DestRect->left)*(SourceRect->right - SourceRect->left)) 983 /(DestRect->right-DestRect->left); 984 } 985 DstY++; 986 SrcY = SourceRect->top + ((DstY-DestRect->top)*(SourceRect->bottom - SourceRect->top)) 987 /(DestRect->bottom-DestRect->top); 988 } 989 } 990 991 EXLATEOBJ_vCleanup(&exloSrcRGB); 992 993 return TRUE; 994 } 995 996 /* EOF */ 997