1 /* 2 * PROJECT: Win32 subsystem 3 * LICENSE: See COPYING in the top level directory 4 * FILE: subsystems/win32/win32k/dib/dib16bpp.c 5 * PURPOSE: Device Independant Bitmap functions, 16bpp 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_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c) 18 { 19 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta; 20 PWORD addr = (PWORD)byteaddr + x; 21 22 *addr = (WORD)c; 23 } 24 25 ULONG 26 DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y) 27 { 28 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta; 29 PWORD addr = (PWORD)byteaddr + x; 30 return (ULONG)(*addr); 31 } 32 33 VOID 34 DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c) 35 { 36 PDWORD addr = (PDWORD)((PWORD)((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta) + x1); 37 38 #if defined(_M_IX86) && !defined(_MSC_VER) 39 /* This is about 10% faster than the generic C code below */ 40 LONG Count = x2 - x1; 41 42 __asm__ __volatile__ ( 43 " cld\n" 44 " mov %0, %%eax\n" 45 " shl $16, %%eax\n" 46 " andl $0xffff, %0\n" /* If the pixel value is "abcd", put "abcdabcd" in %eax */ 47 " or %0, %%eax\n" 48 " mov %2, %%edi\n" 49 " test $0x03, %%edi\n" /* Align to fullword boundary */ 50 " jz 0f\n" 51 " stosw\n" 52 " dec %1\n" 53 " jz 1f\n" 54 "0:\n" 55 " mov %1,%%ecx\n" /* Setup count of fullwords to fill */ 56 " shr $1,%%ecx\n" 57 " rep stosl\n" /* The actual fill */ 58 " test $0x01, %1\n" /* One left to do at the right side? */ 59 " jz 1f\n" 60 " stosw\n" 61 "1:\n" 62 : /* no output */ 63 : "r"(c), "r"(Count), "m"(addr) 64 : "%eax", "%ecx", "%edi"); 65 #else /* _M_IX86 */ 66 LONG cx = x1; 67 DWORD cc; 68 69 if (0 != (cx & 0x01)) 70 { 71 *((PWORD) addr) = (WORD)c; 72 cx++; 73 addr = (PDWORD)((PWORD)(addr) + 1); 74 } 75 cc = ((c & 0xffff) << 16) | (c & 0xffff); 76 while(cx + 1 < x2) 77 { 78 *addr++ = cc; 79 cx += 2; 80 } 81 if (cx < x2) 82 { 83 *((PWORD) addr) = (WORD)c; 84 } 85 #endif /* _M_IX86 */ 86 } 87 88 89 VOID 90 DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c) 91 { 92 #if defined(_M_IX86) && !defined(_MSC_VER) 93 asm volatile( 94 " testl %2, %2" "\n\t" 95 " jle 2f" "\n\t" 96 " movl %2, %%ecx" "\n\t" 97 " shrl $2, %2" "\n\t" 98 " andl $3, %%ecx" "\n\t" 99 " jz 1f" "\n\t" 100 "0:" "\n\t" 101 " movw %%ax, (%0)" "\n\t" 102 " addl %1, %0" "\n\t" 103 " decl %%ecx" "\n\t" 104 " jnz 0b" "\n\t" 105 " testl %2, %2" "\n\t" 106 " jz 2f" "\n\t" 107 "1:" "\n\t" 108 " movw %%ax, (%0)" "\n\t" 109 " addl %1, %0" "\n\t" 110 " movw %%ax, (%0)" "\n\t" 111 " addl %1, %0" "\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 " decl %2" "\n\t" 117 " jnz 1b" "\n\t" 118 "2:" "\n\t" 119 : /* no output */ 120 : "r"((PBYTE)SurfObj->pvScan0 + (y1 * SurfObj->lDelta) + (x * sizeof (WORD))), 121 "r"(SurfObj->lDelta), "r"(y2 - y1), "a"(c) 122 : "cc", "memory", "%ecx"); 123 #else 124 PBYTE byteaddr = (PBYTE)(ULONG_PTR)SurfObj->pvScan0 + y1 * SurfObj->lDelta; 125 PWORD addr = (PWORD)byteaddr + x; 126 LONG lDelta = SurfObj->lDelta; 127 128 byteaddr = (PBYTE)addr; 129 while(y1++ < y2) 130 { 131 *addr = (WORD)c; 132 133 byteaddr += lDelta; 134 addr = (PWORD)byteaddr; 135 } 136 #endif 137 } 138 139 BOOLEAN 140 DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo) 141 { 142 LONG i, j, sx, sy, xColor, f1; 143 PBYTE SourceBits, DestBits, SourceLine, DestLine; 144 PBYTE SourceBits_4BPP, SourceLine_4BPP; 145 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left; 146 147 switch(BltInfo->SourceSurface->iBitmapFormat) 148 { 149 case BMF_1BPP: 150 sx = BltInfo->SourcePoint.x; 151 sy = BltInfo->SourcePoint.y; 152 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++) 153 { 154 sx = BltInfo->SourcePoint.x; 155 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++) 156 { 157 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0) 158 { 159 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, 160 XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0)); 161 } 162 else 163 { 164 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, 165 XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1)); 166 } 167 sx++; 168 } 169 sy++; 170 } 171 break; 172 173 case BMF_4BPP: 174 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + 175 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 176 (BltInfo->SourcePoint.x >> 1); 177 178 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++) 179 { 180 SourceLine_4BPP = SourceBits_4BPP; 181 sx = BltInfo->SourcePoint.x; 182 f1 = sx & 1; 183 184 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++) 185 { 186 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 187 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1))); 188 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor); 189 if(f1 == 1) 190 { 191 SourceLine_4BPP++; 192 f1 = 0; 193 } 194 else 195 { 196 f1 = 1; 197 } 198 sx++; 199 } 200 SourceBits_4BPP += BltInfo->SourceSurface->lDelta; 201 } 202 break; 203 204 case BMF_8BPP: 205 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + 206 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 207 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 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( 218 BltInfo->XlateSourceToDest, *SourceBits); 219 SourceBits += 1; 220 DestBits += 2; 221 } 222 223 SourceLine += BltInfo->SourceSurface->lDelta; 224 DestLine += BltInfo->DestSurface->lDelta; 225 } 226 break; 227 228 case BMF_16BPP: 229 if (NULL == BltInfo->XlateSourceToDest || 0 != 230 (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL)) 231 { 232 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y) 233 { 234 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + 235 (BltInfo->SourcePoint.y * 236 BltInfo->SourceSurface->lDelta) + 2 * 237 BltInfo->SourcePoint.x; 238 239 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) 240 { 241 RtlMoveMemory(DestBits, SourceBits, 242 2 * (BltInfo->DestRect.right - 243 BltInfo->DestRect.left)); 244 245 SourceBits += BltInfo->SourceSurface->lDelta; 246 DestBits += BltInfo->DestSurface->lDelta; 247 } 248 } 249 else 250 { 251 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + 252 ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - 253 BltInfo->DestRect.top - 1) * 254 BltInfo->SourceSurface->lDelta) + 2 * 255 BltInfo->SourcePoint.x; 256 257 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + 258 ((BltInfo->DestRect.bottom - 1) * 259 BltInfo->DestSurface->lDelta) + 2 * 260 BltInfo->DestRect.left; 261 262 for (j = BltInfo->DestRect.bottom - 1; 263 BltInfo->DestRect.top <= j; j--) 264 { 265 RtlMoveMemory(DestBits, SourceBits, 2 * 266 (BltInfo->DestRect.right - 267 BltInfo->DestRect.left)); 268 269 SourceBits -= BltInfo->SourceSurface->lDelta; 270 DestBits -= BltInfo->DestSurface->lDelta; 271 } 272 } 273 } 274 else 275 { 276 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y) 277 { 278 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + 279 (BltInfo->SourcePoint.y * 280 BltInfo->SourceSurface->lDelta) + 2 * 281 BltInfo->SourcePoint.x; 282 283 DestLine = DestBits; 284 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) 285 { 286 SourceBits = SourceLine; 287 DestBits = DestLine; 288 for (i = BltInfo->DestRect.left; i < 289 BltInfo->DestRect.right; i++) 290 { 291 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( 292 BltInfo->XlateSourceToDest, 293 *((WORD *)SourceBits)); 294 SourceBits += 2; 295 DestBits += 2; 296 } 297 SourceLine += BltInfo->SourceSurface->lDelta; 298 DestLine += BltInfo->DestSurface->lDelta; 299 } 300 } 301 else 302 { 303 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + 304 ((BltInfo->SourcePoint.y + 305 BltInfo->DestRect.bottom - 306 BltInfo->DestRect.top - 1) * 307 BltInfo->SourceSurface->lDelta) + 2 * 308 BltInfo->SourcePoint.x; 309 310 DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 + 311 ((BltInfo->DestRect.bottom - 1) * 312 BltInfo->DestSurface->lDelta) + 2 * 313 BltInfo->DestRect.left; 314 315 for (j = BltInfo->DestRect.bottom - 1; 316 BltInfo->DestRect.top <= j; j--) 317 { 318 SourceBits = SourceLine; 319 DestBits = DestLine; 320 for (i = BltInfo->DestRect.left; i < 321 BltInfo->DestRect.right; i++) 322 { 323 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( 324 BltInfo->XlateSourceToDest, 325 *((WORD *)SourceBits)); 326 SourceBits += 2; 327 DestBits += 2; 328 } 329 SourceLine -= BltInfo->SourceSurface->lDelta; 330 DestLine -= BltInfo->DestSurface->lDelta; 331 } 332 } 333 } 334 break; 335 336 case BMF_24BPP: 337 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + 338 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 339 3 * BltInfo->SourcePoint.x; 340 341 DestLine = DestBits; 342 343 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) 344 { 345 SourceBits = SourceLine; 346 DestBits = DestLine; 347 348 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++) 349 { 350 xColor = (*(SourceBits + 2) << 0x10) + 351 (*(SourceBits + 1) << 0x08) + (*(SourceBits)); 352 353 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( 354 BltInfo->XlateSourceToDest, xColor); 355 356 SourceBits += 3; 357 DestBits += 2; 358 } 359 SourceLine += BltInfo->SourceSurface->lDelta; 360 DestLine += BltInfo->DestSurface->lDelta; 361 } 362 break; 363 364 case BMF_32BPP: 365 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + 366 (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 367 4 * BltInfo->SourcePoint.x; 368 369 DestLine = DestBits; 370 371 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++) 372 { 373 SourceBits = SourceLine; 374 DestBits = DestLine; 375 376 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++) 377 { 378 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate( 379 BltInfo->XlateSourceToDest, 380 *((PDWORD) SourceBits)); 381 SourceBits += 4; 382 DestBits += 2; 383 } 384 385 SourceLine += BltInfo->SourceSurface->lDelta; 386 DestLine += BltInfo->DestSurface->lDelta; 387 } 388 break; 389 390 default: 391 DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", 392 BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat)); 393 return FALSE; 394 } 395 396 return TRUE; 397 } 398 399 /* Optimize for bitBlt */ 400 BOOLEAN 401 DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color) 402 { 403 LONG DestY; 404 405 #if defined(_M_IX86) && !defined(_MSC_VER) 406 /* This is about 10% faster than the generic C code below */ 407 ULONG delta = DestSurface->lDelta; 408 ULONG width = (DestRect->right - DestRect->left) ; 409 PULONG pos = (PULONG) ((PBYTE)DestSurface->pvScan0 + DestRect->top * delta + (DestRect->left<<1)); 410 color = (color&0xffff); /* If the color value is "abcd", put "abcdabcd" into color */ 411 color += (color<<16); 412 413 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++) 414 { 415 __asm__ __volatile__ ( 416 "cld\n\t" 417 "mov %1,%%ebx\n\t" 418 "mov %2,%%edi\n\t" 419 "test $0x03, %%edi\n\t" /* Align to fullword boundary */ 420 "jz 1f\n\t" 421 "stosw\n\t" 422 "dec %%ebx\n\t" 423 "jz 2f\n" 424 "1:\n\t" 425 "mov %%ebx,%%ecx\n\t" /* Setup count of fullwords to fill */ 426 "shr $1,%%ecx\n\t" 427 "rep stosl\n\t" /* The actual fill */ 428 "test $0x01, %%ebx\n\t" /* One left to do at the right side? */ 429 "jz 2f\n\t" 430 "stosw\n" 431 "2:" 432 : 433 : "a" (color), "r" (width), "m" (pos) 434 : "%ecx", "%ebx", "%edi"); 435 pos =(PULONG)((ULONG_PTR)pos + delta); 436 } 437 #else /* _M_IX86 */ 438 439 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++) 440 { 441 DIB_16BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color); 442 } 443 #endif 444 return TRUE; 445 } 446 447 BOOLEAN 448 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, 449 RECTL* DestRect, RECTL *SourceRect, 450 XLATEOBJ *ColorTranslation, ULONG iTransColor) 451 { 452 LONG RoundedRight, X, Y, SourceX = 0, SourceY = 0, wd; 453 ULONG *DestBits, Source, Dest; 454 455 LONG DstHeight; 456 LONG DstWidth; 457 LONG SrcHeight; 458 LONG SrcWidth; 459 460 DstHeight = DestRect->bottom - DestRect->top; 461 DstWidth = DestRect->right - DestRect->left; 462 SrcHeight = SourceRect->bottom - SourceRect->top; 463 SrcWidth = SourceRect->right - SourceRect->left; 464 465 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1); 466 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 + 467 (DestRect->left << 1) + 468 DestRect->top * DestSurf->lDelta); 469 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1); 470 471 for(Y = DestRect->top; Y < DestRect->bottom; Y++) 472 { 473 SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight; 474 for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2) 475 { 476 Dest = *DestBits; 477 478 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth; 479 if (SourceX >= 0 && SourceY >= 0 && 480 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY) 481 { 482 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY); 483 if(Source != iTransColor) 484 { 485 Dest &= 0xFFFF0000; 486 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF); 487 } 488 } 489 490 SourceX = SourceRect->left+(X+1 - DestRect->left) * SrcWidth / DstWidth; 491 if (SourceX >= 0 && SourceY >= 0 && 492 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY) 493 { 494 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY); 495 if(Source != iTransColor) 496 { 497 Dest &= 0xFFFF; 498 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16); 499 } 500 } 501 502 *DestBits = Dest; 503 } 504 505 if(X < DestRect->right) 506 { 507 SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth; 508 if (SourceX >= 0 && SourceY >= 0 && 509 SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY) 510 { 511 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY); 512 if(Source != iTransColor) 513 { 514 *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation, 515 Source); 516 } 517 } 518 519 DestBits = (PULONG)((ULONG_PTR)DestBits + 2); 520 } 521 522 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd); 523 } 524 525 return TRUE; 526 } 527 528 /* EOF */ 529