1 2#ifdef HAVE_XORG_CONFIG_H 3#include <xorg-config.h> 4#endif 5 6#include <string.h> 7 8#include "misc.h" 9#include "xf86.h" 10#include "xf86_OSproc.h" 11 12#include <X11/X.h> 13#include "scrnintstr.h" 14#include "gc.h" 15#include "mi.h" 16#include "pixmapstr.h" 17#include "windowstr.h" 18#include "regionstr.h" 19#include "servermd.h" 20#include "xf86str.h" 21#include "xaa.h" 22#include "xaacexp.h" 23#include "xaalocal.h" 24#include "xaawrap.h" 25 26#define MAX_COLOR 32 27#define MAX_MONO 32 28#define MAX_8 32 29#define MAX_128 32 30#define MAX_256 32 31#define MAX_512 16 32 33static int CacheInitIndex = -1; 34#define CACHEINIT(p) ((p)->privates[CacheInitIndex].val) 35 36 37typedef struct _CacheLink { 38 int x; 39 int y; 40 int w; 41 int h; 42 struct _CacheLink *next; 43} CacheLink, *CacheLinkPtr; 44 45 46static void 47TransferList(CacheLinkPtr list, XAACacheInfoPtr array, int num) 48{ 49 while(num--) { 50 array->x = list->x; 51 array->y = list->y; 52 array->w = list->w; 53 array->h = list->h; 54 array->serialNumber = 0; 55 array->fg = array->bg = -1; 56 list = list->next; 57 array++; 58 } 59} 60 61 62 63static CacheLinkPtr 64Enlist(CacheLinkPtr link, int x, int y, int w, int h) 65{ 66 CacheLinkPtr newLink; 67 68 newLink = malloc(sizeof(CacheLink)); 69 newLink->next = link; 70 newLink->x = x; newLink->y = y; 71 newLink->w = w; newLink->h = h; 72 return newLink; 73} 74 75 76 77static CacheLinkPtr 78Delist(CacheLinkPtr link) { 79 CacheLinkPtr ret = NULL; 80 81 if(link) { 82 ret = link->next; 83 free(link); 84 } 85 return ret; 86} 87 88 89 90static void 91FreeList(CacheLinkPtr link) { 92 CacheLinkPtr tmp; 93 94 while(link) { 95 tmp = link; 96 link = link->next; 97 free(tmp); 98 } 99} 100 101 102 103static CacheLinkPtr 104QuadLinks(CacheLinkPtr big, CacheLinkPtr little) 105{ 106 /* CAUTION: This doesn't free big */ 107 int w1, w2, h1, h2; 108 109 while(big) { 110 w1 = big->w >> 1; 111 w2 = big->w - w1; 112 h1 = big->h >> 1; 113 h2 = big->h - h1; 114 115 little = Enlist(little, big->x, big->y, w1, h1); 116 little = Enlist(little, big->x + w1, big->y, w2, h1); 117 little = Enlist(little, big->x, big->y + h1, w1, h2); 118 little = Enlist(little, big->x + w1, big->y + h1, w2, h2); 119 120 big = big->next; 121 } 122 return little; 123} 124 125 126static void 127SubdivideList(CacheLinkPtr *large, CacheLinkPtr *small) 128{ 129 CacheLinkPtr big = *large; 130 CacheLinkPtr little = *small; 131 int size = big->w >> 1; 132 133 little = Enlist(little, big->x, big->y, size, size); 134 little = Enlist(little, big->x + size, big->y, size, size); 135 little = Enlist(little, big->x, big->y + size, size, size); 136 little = Enlist(little, big->x + size, big->y + size, size, size); 137 *small = little; 138 big = Delist(big); 139 *large = big; 140} 141 142static void 143FreePixmapCachePrivate(XAAPixmapCachePrivatePtr pPriv) 144{ 145 if(!pPriv) return; 146 147 free(pPriv->Info512); 148 free(pPriv->Info256); 149 free(pPriv->Info128); 150 free(pPriv->InfoColor); 151 free(pPriv->InfoMono); 152 free(pPriv->InfoPartial); 153 154 free(pPriv); 155} 156 157void 158XAAClosePixmapCache(ScreenPtr pScreen) 159{ 160 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); 161 162 if(infoRec->PixmapCachePrivate) 163 FreePixmapCachePrivate( 164 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate); 165 166 infoRec->PixmapCachePrivate = NULL; 167} 168 169 170 171static CacheLinkPtr 172ThinOutPartials( 173 CacheLinkPtr ListPartial, 174 int *num, int *maxw, int *maxh 175) { 176/* This guy's job is to get at least 4 big slots out of a list of fragments */ 177 178 CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; 179 int Num64, Num32, Num16, Num8, NumKeepers; 180 int w, h; 181 182 List64 = List32 = List16 = List8 = ListKeepers = NULL; 183 Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; 184 w = h = 0; 185 186 /* We sort partials by how large a square tile they can cache. 187 If a partial can't store a 64x64, 32x32, 16x16 or 8x8 tile, 188 we free it. */ 189 190 pCur = ListPartial; 191 while(pCur) { 192 next = pCur->next; 193 if((pCur->w >= 64) && (pCur->h >= 64)) { 194 pCur->next = List64; List64 = pCur; 195 Num64++; 196 } else 197 if((pCur->w >= 32) && (pCur->h >= 32)) { 198 pCur->next = List32; List32 = pCur; 199 Num32++; 200 } else 201 if((pCur->w >= 16) && (pCur->h >= 16)) { 202 pCur->next = List16; List16 = pCur; 203 Num16++; 204 } else 205 if((pCur->w >= 8) && (pCur->h >= 8)) { 206 pCur->next = List8; List8 = pCur; 207 Num8++; 208 } else { 209 free(pCur); 210 } 211 212 pCur = next; 213 } 214 215 /* We save all the tiles from the largest bin that we can get 216 at least 4 of. If there are too few of a bigger slot, we 217 cut it in fourths to make smaller slots. */ 218 219 if(Num64 >= 4) { 220 ListKeepers = List64; List64 = NULL; 221 NumKeepers = Num64; 222 goto GOT_EM; 223 } else if(Num64) { 224 List32 = QuadLinks(List64, List32); 225 Num32 += Num64 * 4; 226 Num64 = 0; 227 } 228 229 if(Num32 >= 4) { 230 ListKeepers = List32; List32 = NULL; 231 NumKeepers = Num32; 232 goto GOT_EM; 233 } else if(Num32) { 234 List16 = QuadLinks(List32, List16); 235 Num16 += Num32 * 4; 236 Num32 = 0; 237 } 238 239 if(Num16 >= 4) { 240 ListKeepers = List16; List16 = NULL; 241 NumKeepers = Num16; 242 goto GOT_EM; 243 } else if(Num16) { 244 List8 = QuadLinks(List16, List8); 245 Num8 += Num16 * 4; 246 Num16 = 0; 247 } 248 249 if(Num8 >= 4) { 250 ListKeepers = List8; List8 = NULL; 251 NumKeepers = Num8; 252 goto GOT_EM; 253 } 254 255GOT_EM: 256 257 /* Free the ones we aren't using */ 258 259 if(List64) FreeList(List64); 260 if(List32) FreeList(List32); 261 if(List16) FreeList(List16); 262 if(List8) FreeList(List8); 263 264 265 /* Enlarge the slots if we can */ 266 267 if(ListKeepers) { 268 CacheLinkPtr pLink = ListKeepers; 269 w = h = 128; 270 271 while(pLink) { 272 if(pLink->w < w) w = pLink->w; 273 if(pLink->h < h) h = pLink->h; 274 pLink = pLink->next; 275 } 276 } 277 278 *maxw = w; 279 *maxh = h; 280 *num = NumKeepers; 281 return ListKeepers; 282} 283 284static void 285ConvertColorToMono( 286 CacheLinkPtr *ColorList, 287 int ColorW, int ColorH, 288 CacheLinkPtr *MonoList, 289 int MonoW, int MonoH 290){ 291 int x, y, w; 292 293 x = (*ColorList)->x; y = (*ColorList)->y; 294 *ColorList = Delist(*ColorList); 295 296 while(ColorH) { 297 ColorH -= MonoH; 298 for(w = 0; w <= (ColorW - MonoW); w += MonoW) 299 *MonoList = Enlist(*MonoList, x + w, y + ColorH, MonoW, MonoH); 300 } 301} 302 303static void 304ConvertAllPartialsTo8x8( 305 int *NumMono, int *NumColor, 306 CacheLinkPtr ListPartial, 307 CacheLinkPtr *ListMono, 308 CacheLinkPtr *ListColor, 309 XAAInfoRecPtr infoRec 310){ 311/* This guy extracts as many 8x8 slots as it can out of fragments */ 312 313 int ColorH = infoRec->CacheHeightColor8x8Pattern; 314 int ColorW = infoRec->CacheWidthColor8x8Pattern; 315 int MonoH = infoRec->CacheHeightMono8x8Pattern; 316 int MonoW = infoRec->CacheWidthMono8x8Pattern; 317 int x, y, w, Height, Width; 318 Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); 319 Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); 320 CacheLinkPtr pLink = ListPartial; 321 CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; 322 323 if(DoColor && DoMono) { 324 /* we assume color patterns take more space than color ones */ 325 if(MonoH > ColorH) ColorH = MonoH; 326 if(MonoW > ColorW) ColorW = MonoW; 327 } 328 329 /* Break up the area into as many Color and Mono slots as we can */ 330 331 while(pLink) { 332 Height = pLink->h; 333 Width = pLink->w; 334 x = pLink->x; 335 y = pLink->y; 336 337 if(DoColor) { 338 while(Height >= ColorH) { 339 Height -= ColorH; 340 for(w = 0; w <= (Width - ColorW); w += ColorW) { 341 ColorList = Enlist( 342 ColorList, x + w, y + Height, ColorW, ColorH); 343 (*NumColor)++; 344 } 345 } 346 } 347 348 if(DoMono && (Height >= MonoH)) { 349 while(Height >= MonoH) { 350 Height -= MonoH; 351 for(w = 0; w <= (Width - MonoW); w += MonoW) { 352 MonoList = Enlist( 353 MonoList, x + w, y + Height, MonoW, MonoH); 354 (*NumMono)++; 355 } 356 } 357 } 358 359 pLink = pLink->next; 360 } 361 362 363 *ListMono = MonoList; 364 *ListColor = ColorList; 365 FreeList(ListPartial); 366} 367 368 369static CacheLinkPtr 370ExtractOneThatFits(CacheLinkPtr *initList, int w, int h) 371{ 372 CacheLinkPtr list = *initList; 373 CacheLinkPtr prev = NULL; 374 375 while(list) { 376 if((list->w >= w) && (list->h >= h)) 377 break; 378 prev = list; 379 list = list->next; 380 } 381 382 if(list) { 383 if(prev) 384 prev->next = list->next; 385 else 386 *initList = list->next; 387 388 list->next = NULL; 389 } 390 391 return list; 392} 393 394 395static CacheLinkPtr 396ConvertSomePartialsTo8x8( 397 int *NumMono, int *NumColor, int *NumPartial, 398 CacheLinkPtr ListPartial, 399 CacheLinkPtr *ListMono, 400 CacheLinkPtr *ListColor, 401 int *maxw, int *maxh, 402 XAAInfoRecPtr infoRec 403){ 404/* This guy tries to get 4 of each type of 8x8 slot requested out of 405 a list of fragments all while trying to retain some big fragments 406 for the cache blits */ 407 408 int ColorH = infoRec->CacheHeightColor8x8Pattern; 409 int ColorW = infoRec->CacheWidthColor8x8Pattern; 410 int MonoH = infoRec->CacheHeightMono8x8Pattern; 411 int MonoW = infoRec->CacheWidthMono8x8Pattern; 412 Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); 413 Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); 414 CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; 415 CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; 416 int Num64, Num32, Num16, Num8, NumKeepers; 417 int w, h, Width, Height; 418 int MonosPerColor = 1; 419 420 if(DoColor && DoMono) { 421 /* we assume color patterns take more space than color ones */ 422 if(MonoH > ColorH) ColorH = MonoH; 423 if(MonoW > ColorW) ColorW = MonoW; 424 MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW); 425 } 426 427 List64 = List32 = List16 = List8 = ListKeepers = MonoList = ColorList = NULL; 428 Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; 429 Width = Height = 0; 430 431 /* We sort partials by how large a square tile they can cache. 432 We make 8x8 patterns from the leftovers if we can. */ 433 434 pCur = ListPartial; 435 while(pCur) { 436 next = pCur->next; 437 if((pCur->w >= 64) && (pCur->h >= 64)) { 438 pCur->next = List64; List64 = pCur; 439 Num64++; 440 } else 441 if((pCur->w >= 32) && (pCur->h >= 32)) { 442 pCur->next = List32; List32 = pCur; 443 Num32++; 444 } else 445 if((pCur->w >= 16) && (pCur->h >= 16)) { 446 pCur->next = List16; List16 = pCur; 447 Num16++; 448 } else 449 if((pCur->w >= 8) && (pCur->h >= 8)) { 450 pCur->next = List8; List8 = pCur; 451 Num8++; 452 } else { 453 h = pCur->h; 454 if(DoColor && (pCur->w >= ColorW) && (h >= ColorH)) { 455 while(h >= ColorH) { 456 h -= ColorH; 457 for(w = 0; w <= (pCur->w - ColorW); w += ColorW) { 458 ColorList = Enlist( ColorList, 459 pCur->x + w, pCur->y + h, ColorW, ColorH); 460 (*NumColor)++; 461 } 462 } 463 } 464 if(DoMono && (pCur->w >= MonoW) && (h >= MonoH)) { 465 while(h >= MonoH) { 466 h -= MonoH; 467 for(w = 0; w <= (pCur->w - MonoW); w += MonoW) { 468 MonoList = Enlist( MonoList, 469 pCur->x + w, pCur->y + h, MonoW, MonoH); 470 (*NumMono)++; 471 } 472 } 473 } 474 free(pCur); 475 } 476 477 pCur = next; 478 } 479 480 /* Try to extract at least 4 of each type of 8x8 slot that we need */ 481 482 if(DoColor) { 483 CacheLinkPtr theOne; 484 while(*NumColor < 4) { 485 theOne = NULL; 486 if(Num8) { 487 if((theOne = ExtractOneThatFits(&List8, ColorW, ColorH))) 488 Num8--; 489 } 490 if(Num16 && !theOne) { 491 if((theOne = ExtractOneThatFits(&List16, ColorW, ColorH))) 492 Num16--; 493 } 494 if(Num32 && !theOne) { 495 if((theOne = ExtractOneThatFits(&List32, ColorW, ColorH))) 496 Num32--; 497 } 498 if(Num64 && !theOne) { 499 if((theOne = ExtractOneThatFits(&List64, ColorW, ColorH))) 500 Num64--; 501 } 502 503 if(!theOne) break; 504 505 506 ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, 507 &MonoList, &ColorList, infoRec); 508 509 if(DoMono) { 510 while(*NumColor && (*NumMono < 4)) { 511 ConvertColorToMono(&ColorList, ColorW, ColorH, 512 &MonoList, MonoW, MonoH); 513 (*NumColor)--; *NumMono += MonosPerColor; 514 } 515 } 516 } 517 } 518 519 if(DoMono) { 520 CacheLinkPtr theOne; 521 while(*NumMono < 4) { 522 theOne = NULL; 523 if(Num8) { 524 if((theOne = ExtractOneThatFits(&List8, MonoW, MonoH))) 525 Num8--; 526 } 527 if(Num16 && !theOne) { 528 if((theOne = ExtractOneThatFits(&List16, MonoW, MonoH))) 529 Num16--; 530 } 531 if(Num32 && !theOne) { 532 if((theOne = ExtractOneThatFits(&List32, MonoW, MonoH))) 533 Num32--; 534 } 535 if(Num64 && !theOne) { 536 if((theOne = ExtractOneThatFits(&List64, MonoW, MonoH))) 537 Num64--; 538 } 539 540 if(!theOne) break; 541 542 ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, 543 &MonoList, &ColorList, infoRec); 544 } 545 } 546 547 /* We save all the tiles from the largest bin that we can get 548 at least 4 of. If there are too few of a bigger slot, we 549 cut it in fourths to make smaller slots. */ 550 551 if(Num64 >= 4) { 552 ListKeepers = List64; List64 = NULL; 553 NumKeepers = Num64; 554 goto GOT_EM; 555 } else if(Num64) { 556 List32 = QuadLinks(List64, List32); 557 Num32 += Num64 * 4; 558 Num64 = 0; 559 } 560 561 if(Num32 >= 4) { 562 ListKeepers = List32; List32 = NULL; 563 NumKeepers = Num32; 564 goto GOT_EM; 565 } else if(Num32) { 566 List16 = QuadLinks(List32, List16); 567 Num16 += Num32 * 4; 568 Num32 = 0; 569 } 570 571 if(Num16 >= 4) { 572 ListKeepers = List16; List16 = NULL; 573 NumKeepers = Num16; 574 goto GOT_EM; 575 } else if(Num16) { 576 List8 = QuadLinks(List16, List8); 577 Num8 += Num16 * 4; 578 Num16 = 0; 579 } 580 581 if(Num8 >= 4) { 582 ListKeepers = List8; List8 = NULL; 583 NumKeepers = Num8; 584 goto GOT_EM; 585 } 586 587GOT_EM: 588 589 /* Free the ones we aren't using */ 590 591 if(List64) 592 ConvertAllPartialsTo8x8(NumMono, NumColor, List64, 593 &MonoList, &ColorList, infoRec); 594 if(List32) 595 ConvertAllPartialsTo8x8(NumMono, NumColor, List32, 596 &MonoList, &ColorList, infoRec); 597 if(List16) 598 ConvertAllPartialsTo8x8(NumMono, NumColor, List16, 599 &MonoList, &ColorList, infoRec); 600 if(List8) 601 ConvertAllPartialsTo8x8(NumMono, NumColor, List8, 602 &MonoList, &ColorList, infoRec); 603 604 605 /* Enlarge the slots if we can */ 606 607 if(ListKeepers) { 608 CacheLinkPtr pLink = ListKeepers; 609 Width = Height = 128; 610 611 while(pLink) { 612 if(pLink->w < Width) Width = pLink->w; 613 if(pLink->h < Height) Height = pLink->h; 614 pLink = pLink->next; 615 } 616 } 617 618 *ListMono = MonoList; 619 *ListColor = ColorList; 620 *maxw = Width; 621 *maxh = Height; 622 *NumPartial = NumKeepers; 623 return ListKeepers; 624} 625 626 627void 628XAAInitPixmapCache( 629 ScreenPtr pScreen, 630 RegionPtr areas, 631 pointer data 632) { 633 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 634 XAAInfoRecPtr infoRec = (XAAInfoRecPtr)data; 635 XAAPixmapCachePrivatePtr pCachePriv; 636 BoxPtr pBox = RegionRects(areas); 637 int nBox = RegionNumRects(areas); 638 int Num512, Num256, Num128, NumPartial, NumColor, NumMono; 639 int Target512, Target256; 640 CacheLinkPtr List512, List256, List128, ListPartial, ListColor, ListMono; 641 int x, y, w, h, ntotal, granularity, width, height, i; 642 int MaxPartialWidth, MaxPartialHeight; 643 644 infoRec->MaxCacheableTileWidth = 0; 645 infoRec->MaxCacheableTileHeight = 0; 646 infoRec->MaxCacheableStippleHeight = 0; 647 infoRec->MaxCacheableStippleWidth = 0; 648 infoRec->UsingPixmapCache = FALSE; 649 650 651 if(!nBox || !pBox || !(infoRec->Flags & PIXMAP_CACHE)) 652 return; 653 654 /* Allocate a persistent per-screen init flag to control messages */ 655 if (CacheInitIndex < 0) 656 CacheInitIndex = xf86AllocateScrnInfoPrivateIndex(); 657 658 /* free the old private data if it exists */ 659 if(infoRec->PixmapCachePrivate) { 660 FreePixmapCachePrivate( 661 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate); 662 infoRec->PixmapCachePrivate = NULL; 663 } 664 665 Num512 = Num256 = Num128 = NumPartial = NumMono = NumColor = 0; 666 List512 = List256 = List128 = ListPartial = ListMono = ListColor = NULL; 667 granularity = infoRec->CachePixelGranularity; 668 if(granularity <= 1) granularity = 0; 669 670 /* go through the boxes and break it into as many pieces as we can fit */ 671 672 while(nBox--) { 673 x = pBox->x1; 674 if(granularity) { 675 int tmp = x % granularity; 676 if(tmp) x += (granularity - tmp); 677 } 678 width = pBox->x2 - x; 679 if(width <= 0) {pBox++; continue;} 680 681 y = pBox->y1; 682 height = pBox->y2 - y; 683 684 for(h = 0; h <= (height - 512); h += 512) { 685 for(w = 0; w <= (width - 512); w += 512) { 686 List512 = Enlist(List512, x + w, y + h, 512, 512); 687 Num512++; 688 } 689 for(; w <= (width - 256); w += 256) { 690 List256 = Enlist(List256, x + w, y + h, 256, 256); 691 List256 = Enlist(List256, x + w, y + h + 256, 256, 256); 692 Num256 += 2; 693 } 694 for(; w <= (width - 128); w += 128) { 695 List128 = Enlist(List128, x + w, y + h, 128, 128); 696 List128 = Enlist(List128, x + w, y + h + 128, 128, 128); 697 List128 = Enlist(List128, x + w, y + h + 256, 128, 128); 698 List128 = Enlist(List128, x + w, y + h + 384, 128, 128); 699 Num128 += 4; 700 } 701 if(w < width) { 702 int d = width - w; 703 ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); 704 ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); 705 ListPartial = Enlist(ListPartial, x + w, y + h + 256, d, 128); 706 ListPartial = Enlist(ListPartial, x + w, y + h + 384, d, 128); 707 NumPartial += 4; 708 } 709 } 710 for(; h <= (height - 256); h += 256) { 711 for(w = 0; w <= (width - 256); w += 256) { 712 List256 = Enlist(List256, x + w, y + h, 256, 256); 713 Num256++; 714 } 715 for(; w <= (width - 128); w += 128) { 716 List128 = Enlist(List128, x + w, y + h, 128, 128); 717 List128 = Enlist(List128, x + w, y + h + 128, 128, 128); 718 Num128 += 2; 719 } 720 if(w < width) { 721 int d = width - w; 722 ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); 723 ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); 724 NumPartial += 2; 725 } 726 } 727 for(; h <= (height - 128); h += 128) { 728 for(w = 0; w <= (width - 128); w += 128) { 729 List128 = Enlist(List128, x + w, y + h, 128, 128); 730 Num128++; 731 } 732 if(w < width) { 733 ListPartial = Enlist( 734 ListPartial, x + w, y + h, width - w, 128); 735 NumPartial++; 736 } 737 } 738 if(h < height) { 739 int d = height - h; 740 for(w = 0; w <= (width - 128); w += 128) { 741 ListPartial = Enlist(ListPartial, x + w, y + h, 128, d); 742 NumPartial++; 743 } 744 if(w < width) { 745 ListPartial = Enlist(ListPartial, x + w, y + h, width - w, d); 746 NumPartial++; 747 } 748 } 749 pBox++; 750 } 751 752 753/* 754 by this point we've carved the space into as many 512x512, 256x256 755 and 128x128 blocks as we could fit. We will then break larger 756 blocks into smaller ones if we need to. The rules are as follows: 757 758 512x512 - 759 1) Don't take up more than half the memory. 760 2) Don't bother if you can't get at least four. 761 3) Don't make more than MAX_512. 762 4) Don't have any of there are no 256x256s. 763 764 256x256 - 765 1) Don't take up more than a quarter of the memory enless there 766 aren't any 512x512s. Then we can take up to half. 767 2) Don't bother if you can't get at least four. 768 3) Don't make more than MAX_256. 769 770 128x128 - 771 1) Don't make more than MAX_128. 772 773 We don't bother with the partial blocks unless we can use them 774 for 8x8 pattern fills or we are short on larger blocks. 775 776*/ 777 778 ntotal = Num128 + (Num256<<2) + (Num512<<4); 779 780 Target512 = ntotal >> 5; 781 if(Target512 < 4) Target512 = 0; 782 if(!Target512) Target256 = ntotal >> 3; 783 else Target256 = ntotal >> 4; 784 if(Target256 < 4) Target256 = 0; 785 786 if(Num512 && Num256 < 4) { 787 while(Num512 && Num256 < Target256) { 788 SubdivideList(&List512, &List256); 789 Num256 += 4; Num512--; 790 } 791 } 792 793 if(!Num512) { /* no room */ 794 } else if((Num512 < 4) || (!Target512)) { 795 while(Num512) { 796 SubdivideList(&List512, &List256); 797 Num256 += 4; Num512--; 798 } 799 } else if((Num512 > MAX_512) || (Num512 > Target512)){ 800 while(Num512 > MAX_512) { 801 SubdivideList(&List512, &List256); 802 Num256 += 4; Num512--; 803 } 804 while(Num512 > Target512) { 805 if(Num256 < MAX_256) { 806 SubdivideList(&List512, &List256); 807 Num256 += 4; Num512--; 808 } else break; 809 } 810 } 811 812 if(!Num256) { /* no room */ 813 } else if((Num256 < 4) || (!Target256)) { 814 while(Num256) { 815 SubdivideList(&List256, &List128); 816 Num128 += 4; Num256--; 817 } 818 } else if((Num256 > MAX_256) || (Num256 > Target256)) { 819 while(Num256 > MAX_256) { 820 SubdivideList(&List256, &List128); 821 Num128 += 4; Num256--; 822 } 823 while(Num256 > Target256) { 824 if(Num128 < MAX_128) { 825 SubdivideList(&List256, &List128); 826 Num128 += 4; Num256--; 827 } else break; 828 } 829 } 830 831 if(Num128 && ((Num128 < 4) || (Num128 > MAX_128))) { 832 CacheLinkPtr next; 833 int max = (Num128 > MAX_128) ? MAX_128 : 0; 834 835 /* 836 * Note: next is set in this way to work around a code generation 837 * bug in gcc 2.7.2.3. 838 */ 839 next = List128->next; 840 while(Num128 > max) { 841 List128->next = ListPartial; 842 ListPartial = List128; 843 if((List128 = next)) 844 next = List128->next; 845 NumPartial++; Num128--; 846 } 847 } 848 849 MaxPartialHeight = MaxPartialWidth = 0; 850 851 /* at this point we have as many 512x512 and 256x256 slots as we 852 want but may have an excess of 128x128 slots. We still need 853 to find out if we need 8x8 slots. We take these from the 854 partials if we have them. Otherwise, we break some 128x128's */ 855 856 if(!(infoRec->PixmapCacheFlags & (CACHE_MONO_8x8 | CACHE_COLOR_8x8))) { 857 if(NumPartial) { 858 if(Num128) { /* don't bother with partials */ 859 FreeList(ListPartial); 860 NumPartial = 0; ListPartial = NULL; 861 } else { 862 /* We have no big slots. Weed out the unusable partials */ 863 ListPartial = ThinOutPartials(ListPartial, &NumPartial, 864 &MaxPartialWidth, &MaxPartialHeight); 865 } 866 } 867 } else { 868 int MonosPerColor = 1; 869 int ColorH = infoRec->CacheHeightColor8x8Pattern; 870 int ColorW = infoRec->CacheWidthColor8x8Pattern; 871 int MonoH = infoRec->CacheHeightMono8x8Pattern; 872 int MonoW = infoRec->CacheWidthMono8x8Pattern; 873 Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); 874 Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); 875 876 if(DoColor) infoRec->CanDoColor8x8 = FALSE; 877 if(DoMono) infoRec->CanDoMono8x8 = FALSE; 878 879 if(DoColor && DoMono) { 880 /* we assume color patterns take more space than color ones */ 881 if(MonoH > ColorH) ColorH = MonoH; 882 if(MonoW > ColorW) ColorW = MonoW; 883 MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW); 884 } 885 886 if(Num128) { 887 if(NumPartial) { /* use all for 8x8 slots */ 888 ConvertAllPartialsTo8x8(&NumMono, &NumColor, 889 ListPartial, &ListMono, &ListColor, infoRec); 890 NumPartial = 0; ListPartial = NULL; 891 } 892 893 /* Get some 8x8 slots from the 128 slots */ 894 while((Num128 > 4) && 895 ((NumMono < MAX_MONO) && (NumColor < MAX_COLOR))) { 896 CacheLinkPtr tmp = NULL; 897 898 tmp = Enlist(tmp, List128->x, List128->y, 899 List128->w, List128->h); 900 List128 = Delist(List128); 901 Num128--; 902 903 ConvertAllPartialsTo8x8(&NumMono, &NumColor, 904 tmp, &ListMono, &ListColor, infoRec); 905 } 906 } else if(NumPartial) { 907 /* We have share partials between 8x8 slots and tiles. */ 908 ListPartial = ConvertSomePartialsTo8x8(&NumMono, &NumColor, 909 &NumPartial, ListPartial, &ListMono, &ListColor, 910 &MaxPartialWidth, &MaxPartialHeight, infoRec); 911 } 912 913 914 if(DoMono && DoColor) { 915 if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { 916 int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; 917 918 while(NumColor > max) { 919 ConvertColorToMono(&ListColor, ColorW, ColorH, 920 &ListMono, MonoW, MonoH); 921 NumColor--; NumMono += MonosPerColor; 922 } 923 } 924 925 /* favor Mono slots over Color ones */ 926 while((NumColor > 4) && (NumMono < MAX_MONO)) { 927 ConvertColorToMono(&ListColor, ColorW, ColorH, 928 &ListMono, MonoW, MonoH); 929 NumColor--; NumMono += MonosPerColor; 930 } 931 } 932 933 if(NumMono && ((NumMono > MAX_MONO) || (NumMono < 4))) { 934 int max = (NumMono > MAX_MONO) ? MAX_MONO : 0; 935 936 while(NumMono > max) { 937 ListMono = Delist(ListMono); 938 NumMono--; 939 } 940 } 941 if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { 942 int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; 943 944 while(NumColor > max) { 945 ListColor = Delist(ListColor); 946 NumColor--; 947 } 948 } 949 } 950 951 952 pCachePriv = calloc(1,sizeof(XAAPixmapCachePrivate)); 953 if(!pCachePriv) { 954 if(Num512) FreeList(List512); 955 if(Num256) FreeList(List256); 956 if(Num128) FreeList(List128); 957 if(NumPartial) FreeList(ListPartial); 958 if(NumColor) FreeList(ListColor); 959 if(NumMono) FreeList(ListMono); 960 return; 961 } 962 963 infoRec->PixmapCachePrivate = (char*)pCachePriv; 964 965 if(Num512) { 966 pCachePriv->Info512 = calloc(Num512,sizeof(XAACacheInfoRec)); 967 if(!pCachePriv->Info512) Num512 = 0; 968 if(Num512) TransferList(List512, pCachePriv->Info512, Num512); 969 FreeList(List512); 970 pCachePriv->Num512x512 = Num512; 971 } 972 if(Num256) { 973 pCachePriv->Info256 = calloc(Num256, sizeof(XAACacheInfoRec)); 974 if(!pCachePriv->Info256) Num256 = 0; 975 if(Num256) TransferList(List256, pCachePriv->Info256, Num256); 976 FreeList(List256); 977 pCachePriv->Num256x256 = Num256; 978 } 979 if(Num128) { 980 pCachePriv->Info128 = calloc(Num128, sizeof(XAACacheInfoRec)); 981 if(!pCachePriv->Info128) Num128 = 0; 982 if(Num128) TransferList(List128, pCachePriv->Info128, Num128); 983 FreeList(List128); 984 pCachePriv->Num128x128 = Num128; 985 } 986 987 if(NumPartial) { 988 pCachePriv->InfoPartial = calloc(NumPartial, sizeof(XAACacheInfoRec)); 989 if(!pCachePriv->InfoPartial) NumPartial = 0; 990 if(NumPartial) 991 TransferList(ListPartial, pCachePriv->InfoPartial, NumPartial); 992 FreeList(ListPartial); 993 pCachePriv->NumPartial = NumPartial; 994 } 995 996 if(NumColor) { 997 pCachePriv->InfoColor = calloc(NumColor, sizeof(XAACacheInfoRec)); 998 if(!pCachePriv->InfoColor) NumColor = 0; 999 if(NumColor) TransferList(ListColor, pCachePriv->InfoColor, NumColor); 1000 FreeList(ListColor); 1001 pCachePriv->NumColor = NumColor; 1002 } 1003 1004 if(NumMono) { 1005 pCachePriv->InfoMono = calloc(NumMono, sizeof(XAACacheInfoRec)); 1006 if(!pCachePriv->InfoMono) NumMono = 0; 1007 if(NumMono) TransferList(ListMono, pCachePriv->InfoMono, NumMono); 1008 FreeList(ListMono); 1009 pCachePriv->NumMono = NumMono; 1010 } 1011 1012 1013 if(NumPartial) { 1014 infoRec->MaxCacheableTileWidth = MaxPartialWidth; 1015 infoRec->MaxCacheableTileHeight = MaxPartialHeight; 1016 } 1017 if(Num128) 1018 infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 128; 1019 if(Num256) 1020 infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 256; 1021 if(Num512) 1022 infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 512; 1023 1024 1025 infoRec->MaxCacheableStippleHeight = infoRec->MaxCacheableTileHeight; 1026 infoRec->MaxCacheableStippleWidth = 1027 infoRec->MaxCacheableTileWidth * pScrn->bitsPerPixel; 1028 if(infoRec->ScreenToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) 1029 infoRec->MaxCacheableStippleWidth /= 3; 1030 1031 if(NumMono) { 1032 if(!(infoRec->Mono8x8PatternFillFlags & 1033 (HARDWARE_PATTERN_PROGRAMMED_ORIGIN | 1034 HARDWARE_PATTERN_PROGRAMMED_BITS))) { 1035 int numPerLine = 1036 infoRec->CacheWidthMono8x8Pattern/infoRec->MonoPatternPitch; 1037 1038 for(i = 0; i < 64; i++) { 1039 pCachePriv->MonoOffsets[i].y = i/numPerLine; 1040 pCachePriv->MonoOffsets[i].x = (i % numPerLine) * 1041 infoRec->MonoPatternPitch; 1042 } 1043 } 1044 infoRec->CanDoMono8x8 = TRUE; 1045 } 1046 if(NumColor) { 1047 if(!(infoRec->Color8x8PatternFillFlags & 1048 HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { 1049 1050 for(i = 0; i < 64; i++) { 1051 pCachePriv->ColorOffsets[i].y = i & 0x07; 1052 pCachePriv->ColorOffsets[i].x = i & ~0x07; 1053 } 1054 } 1055 infoRec->CanDoColor8x8 = TRUE; 1056 } 1057 1058 if(!CACHEINIT(pScrn)) { 1059 xf86ErrorF("\tSetting up tile and stipple cache:\n"); 1060 if(NumPartial) 1061 xf86ErrorF("\t\t%i %ix%i slots\n", 1062 NumPartial, MaxPartialWidth, MaxPartialHeight); 1063 if(Num128) xf86ErrorF("\t\t%i 128x128 slots\n", Num128); 1064 if(Num256) xf86ErrorF("\t\t%i 256x256 slots\n", Num256); 1065 if(Num512) xf86ErrorF("\t\t%i 512x512 slots\n", Num512); 1066 if(NumColor) xf86ErrorF("\t\t%i 8x8 color pattern slots\n", NumColor); 1067 if(NumMono) xf86ErrorF("\t\t%i 8x8 color expansion slots\n", NumMono); 1068 } 1069 1070 if(!(NumPartial | Num128 | Num256 | Num512 | NumColor | NumMono)) { 1071 if(!CACHEINIT(pScrn)) 1072 xf86ErrorF("\t\tNot enough video memory for pixmap cache\n"); 1073 } else infoRec->UsingPixmapCache = TRUE; 1074 1075 CACHEINIT(pScrn) = 1; 1076} 1077 1078#if X_BYTE_ORDER == X_BIG_ENDIAN 1079static CARD32 StippleMasks[4] = { 1080 0x80808080, 1081 0xC0C0C0C0, 1082 0x00000000, 1083 0xF0F0F0F0 1084}; 1085#else 1086static CARD32 StippleMasks[4] = { 1087 0x01010101, 1088 0x03030303, 1089 0x00000000, 1090 0x0F0F0F0F 1091}; 1092#endif 1093 1094Bool 1095XAACheckStippleReducibility(PixmapPtr pPixmap) 1096{ 1097 XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); 1098 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); 1099 CARD32 *IntPtr = (CARD32*)pPixmap->devPrivate.ptr; 1100 int w = pPixmap->drawable.width; 1101 int h = pPixmap->drawable.height; 1102 int i; 1103 CARD32 bits[8]; 1104 CARD32 mask = SHIFT_R(0xFFFFFFFF,24); 1105 1106 pPriv->flags |= REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR; 1107 pPriv->flags &= ~REDUCIBLE_TO_8x8; 1108 1109 if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) 1110 return FALSE; 1111 1112 i = (h > 8) ? 8 : h; 1113 1114 switch(w) { 1115 case 32: 1116 while(i--) { 1117 bits[i] = IntPtr[i] & mask; 1118 if( (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask, 8)), 8)) || 1119 (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,16)),16)) || 1120 (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,24)),24))) 1121 return FALSE; 1122 } 1123 break; 1124 case 16: 1125 while(i--) { 1126 bits[i] = IntPtr[i] & mask; 1127 if(bits[i] != ((IntPtr[i] & SHIFT_R(SHIFT_L(mask,8),8)))) 1128 return FALSE; 1129 } 1130 break; 1131 default: 1132 while(i--) 1133 bits[i] = IntPtr[i] & mask; 1134 break; 1135 } 1136 1137 switch(h) { 1138 case 32: 1139 if( (IntPtr[8] != IntPtr[16]) || (IntPtr[9] != IntPtr[17]) || 1140 (IntPtr[10] != IntPtr[18]) || (IntPtr[11] != IntPtr[19]) || 1141 (IntPtr[12] != IntPtr[20]) || (IntPtr[13] != IntPtr[21]) || 1142 (IntPtr[14] != IntPtr[22]) || (IntPtr[15] != IntPtr[23]) || 1143 (IntPtr[16] != IntPtr[24]) || (IntPtr[17] != IntPtr[25]) || 1144 (IntPtr[18] != IntPtr[26]) || (IntPtr[19] != IntPtr[27]) || 1145 (IntPtr[20] != IntPtr[28]) || (IntPtr[21] != IntPtr[29]) || 1146 (IntPtr[22] != IntPtr[30]) || (IntPtr[23] != IntPtr[31])) 1147 return FALSE; 1148 /* fall through */ 1149 case 16: 1150 if( (IntPtr[0] != IntPtr[8]) || (IntPtr[1] != IntPtr[9]) || 1151 (IntPtr[2] != IntPtr[10]) || (IntPtr[3] != IntPtr[11]) || 1152 (IntPtr[4] != IntPtr[12]) || (IntPtr[5] != IntPtr[13]) || 1153 (IntPtr[6] != IntPtr[14]) || (IntPtr[7] != IntPtr[15])) 1154 return FALSE; 1155 case 8: break; 1156 case 1: bits[1] = bits[0]; 1157 case 2: bits[2] = bits[0]; bits[3] = bits[1]; 1158 case 4: bits[4] = bits[0]; bits[5] = bits[1]; 1159 bits[6] = bits[2]; bits[7] = bits[3]; 1160 break; 1161 } 1162 1163 pPriv->flags |= REDUCIBLE_TO_8x8; 1164 1165 pPriv->pattern0 = bits[0] | SHIFT_L(bits[1],8) | SHIFT_L(bits[2],16) | SHIFT_L(bits[3],24); 1166 pPriv->pattern1 = bits[4] | SHIFT_L(bits[5],8) | SHIFT_L(bits[6],16) | SHIFT_L(bits[7],24); 1167 1168 if(w < 8) { 1169 pPriv->pattern0 &= StippleMasks[w - 1]; 1170 pPriv->pattern1 &= StippleMasks[w - 1]; 1171 1172 switch(w) { 1173 case 1: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,1); 1174 pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,1); 1175 case 2: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,2); 1176 pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,2); 1177 case 4: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,4); 1178 pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,4); 1179 } 1180 } 1181 1182 if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { 1183 pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); 1184 pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); 1185 } 1186 1187 1188 return TRUE; 1189} 1190 1191static inline CARD32 1192load_24bits(void *where) 1193{ 1194 unsigned char *bytes = where; 1195 1196 if (__predict_true(((uintptr_t)where & 0x3) == 0)) { 1197 return (*(CARD32 *)where) & 0x00ffffff; 1198 } 1199 1200#if X_BYTE_ORDER == X_LITTLE_ENDIAN 1201 return (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 1202#endif 1203#if X_BYTE_ORDER == X_BIG_ENDIAN 1204 return (bytes[0] << 16) + (bytes[1] << 8) + bytes[2]; 1205#endif 1206} 1207 1208Bool 1209XAACheckTileReducibility(PixmapPtr pPixmap, Bool checkMono) 1210{ 1211 XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); 1212 CARD32 *IntPtr; 1213 int w = pPixmap->drawable.width; 1214 int h = pPixmap->drawable.height; 1215 int pitch = pPixmap->devKind >> 2; 1216 int dwords, i, j; 1217 1218 pPriv->flags |= REDUCIBILITY_CHECKED; 1219 pPriv->flags &= ~(REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR); 1220 1221 if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) 1222 return FALSE; 1223 1224 dwords = ((w * pPixmap->drawable.bitsPerPixel) + 31) >> 5; 1225 i = (h > 8) ? 8 : h; 1226 1227 1228 if(w > 8) { 1229 IntPtr = (CARD32*)pPixmap->devPrivate.ptr; 1230 switch(pPixmap->drawable.bitsPerPixel) { 1231 case 8: 1232 while(i--) { 1233 for(j = 2; j < dwords; j++) 1234 if(IntPtr[j] != IntPtr[j & 0x01]) 1235 return FALSE; 1236 IntPtr += pitch; 1237 } 1238 break; 1239 case 16: 1240 while(i--) { 1241 for(j = 4; j < dwords; j++) 1242 if(IntPtr[j] != IntPtr[j & 0x03]) 1243 return FALSE; 1244 IntPtr += pitch; 1245 } 1246 break; 1247 case 24: 1248 while(i--) { 1249 for(j = 6; j < dwords; j++) 1250 if(IntPtr[j] != IntPtr[j % 6]) 1251 return FALSE; 1252 IntPtr += pitch; 1253 } 1254 break; 1255 case 32: 1256 while(i--) { 1257 for(j = 8; j < dwords; j++) 1258 if(IntPtr[j] != IntPtr[j & 0x07]) 1259 return FALSE; 1260 IntPtr += pitch; 1261 } 1262 break; 1263 default: return FALSE; 1264 } 1265 1266 } 1267 1268 1269 if(h == 32) { 1270 CARD32 *IntPtr2, *IntPtr3, *IntPtr4; 1271 i = 8; 1272 IntPtr = (CARD32*)pPixmap->devPrivate.ptr; 1273 IntPtr2 = IntPtr + (pitch << 3); 1274 IntPtr3 = IntPtr2 + (pitch << 3); 1275 IntPtr4 = IntPtr3 + (pitch << 3); 1276 while(i--) { 1277 for(j = 0; j < dwords; j++) 1278 if((IntPtr[j] != IntPtr2[j]) || (IntPtr[j] != IntPtr3[j]) || 1279 (IntPtr[j] != IntPtr4[j])) 1280 return FALSE; 1281 IntPtr += pitch; 1282 IntPtr2 += pitch; 1283 IntPtr3 += pitch; 1284 IntPtr4 += pitch; 1285 } 1286 } else if (h == 16) { 1287 CARD32 *IntPtr2; 1288 i = 8; 1289 IntPtr = (CARD32*)pPixmap->devPrivate.ptr; 1290 IntPtr2 = IntPtr + (pitch << 3); 1291 while(i--) { 1292 for(j = 0; j < dwords; j++) 1293 if(IntPtr[j] != IntPtr2[j]) 1294 return FALSE; 1295 IntPtr += pitch; 1296 IntPtr2 += pitch; 1297 } 1298 } 1299 1300 pPriv->flags |= REDUCIBLE_TO_8x8; 1301 1302 if(checkMono) { 1303 XAAInfoRecPtr infoRec = 1304 GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); 1305 unsigned char bits[8]; 1306 int fg, bg = -1, x, y; 1307 1308 i = (h > 8) ? 8 : h; 1309 j = (w > 8) ? 8 : w; 1310 1311 if(pPixmap->drawable.bitsPerPixel == 8) { 1312 unsigned char *srcp = pPixmap->devPrivate.ptr; 1313 fg = srcp[0]; 1314 pitch = pPixmap->devKind; 1315 for(y = 0; y < i; y++) { 1316 bits[y] = 0; 1317 for(x = 0; x < j; x++) { 1318 if(srcp[x] != fg) { 1319 if(bg == -1) bg = srcp[x]; 1320 else if(bg != srcp[x]) return TRUE; 1321 } else bits[y] |= 1 << x; 1322 } 1323 srcp += pitch; 1324 } 1325 } else if(pPixmap->drawable.bitsPerPixel == 16) { 1326 unsigned short *srcp = (unsigned short*)pPixmap->devPrivate.ptr; 1327 fg = srcp[0]; 1328 pitch = pPixmap->devKind >> 1; 1329 for(y = 0; y < i; y++) { 1330 bits[y] = 0; 1331 for(x = 0; x < j; x++) { 1332 if(srcp[x] != fg) { 1333 if(bg == -1) bg = srcp[x]; 1334 else if(bg != srcp[x]) return TRUE; 1335 } else bits[y] |= 1 << x; 1336 } 1337 srcp += pitch; 1338 } 1339 } else if(pPixmap->drawable.bitsPerPixel == 24) { 1340 CARD32 val; 1341 unsigned char *srcp = pPixmap->devPrivate.ptr; 1342 fg = load_24bits(srcp); 1343 pitch = pPixmap->devKind; 1344 j *= 3; 1345 for(y = 0; y < i; y++) { 1346 bits[y] = 0; 1347 for(x = 0; x < j; x+=3) { 1348 val = load_24bits(srcp+x); 1349 if(val != fg) { 1350 if(bg == -1) bg = val; 1351 else if(bg != val) 1352 return TRUE; 1353 } else bits[y] |= 1 << (x/3); 1354 } 1355 srcp += pitch; 1356 } 1357 } else if(pPixmap->drawable.bitsPerPixel == 32) { 1358 IntPtr = (CARD32*)pPixmap->devPrivate.ptr; 1359 fg = IntPtr[0]; 1360 for(y = 0; y < i; y++) { 1361 bits[y] = 0; 1362 for(x = 0; x < j; x++) { 1363 if(IntPtr[x] != fg) { 1364 if(bg == -1) bg = IntPtr[x]; 1365 else if(bg != IntPtr[x]) return TRUE; 1366 } else bits[y] |= 1 << x; 1367 } 1368 IntPtr += pitch; 1369 } 1370 } else return TRUE; 1371 1372 pPriv->fg = fg; 1373 if(bg == -1) pPriv->bg = fg; 1374 else pPriv->bg = bg; 1375 1376 if(h < 8) { 1377 switch(h) { 1378 case 1: bits[1] = bits[0]; 1379 case 2: bits[2] = bits[0]; bits[3] = bits[1]; 1380 case 4: bits[4] = bits[0]; bits[5] = bits[1]; 1381 bits[6] = bits[2]; bits[7] = bits[3]; 1382 break; 1383 } 1384 } 1385 1386 pPriv->pattern0 = 1387 bits[0] | (bits[1]<<8) | (bits[2]<<16) | (bits[3]<<24); 1388 pPriv->pattern1 = 1389 bits[4] | (bits[5]<<8) | (bits[6]<<16) | (bits[7]<<24); 1390 1391 if(w < 8) { 1392 switch(w) { 1393 case 1: pPriv->pattern0 |= (pPriv->pattern0 << 1); 1394 pPriv->pattern1 |= (pPriv->pattern1 << 1); 1395 case 2: pPriv->pattern0 |= (pPriv->pattern0 << 2); 1396 pPriv->pattern1 |= (pPriv->pattern1 << 2); 1397 case 4: pPriv->pattern0 |= (pPriv->pattern0 << 4); 1398 pPriv->pattern1 |= (pPriv->pattern1 << 4); 1399 } 1400 } 1401 pPriv->flags |= REDUCIBLE_TO_2_COLOR; 1402 1403 if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { 1404 pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); 1405 pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); 1406 } 1407 1408 } 1409 1410 return TRUE; 1411} 1412 1413 1414void XAATileCache( 1415 ScrnInfoPtr pScrn, 1416 XAACacheInfoPtr pCache, 1417 int w, int h 1418) { 1419 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1420 1421 (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, ~0, -1); 1422 1423 while((w << 1) <= pCache->w) { 1424 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, 1425 pCache->x + w, pCache->y, w, h); 1426 w <<= 1; 1427 } 1428 if(w != pCache->w) { 1429 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, 1430 pCache->x + w, pCache->y, pCache->w - w, h); 1431 w = pCache->w; 1432 } 1433 1434 while((h << 1) <= pCache->h) { 1435 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, 1436 pCache->x, pCache->y + h, w, h); 1437 h <<= 1; 1438 } 1439 if(h != pCache->h) { 1440 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, 1441 pCache->x, pCache->y + h, w, pCache->h - h); 1442 } 1443 SET_SYNC_FLAG(infoRec); 1444} 1445 1446XAACacheInfoPtr 1447XAACacheTile(ScrnInfoPtr pScrn, PixmapPtr pPix) 1448{ 1449 int w = pPix->drawable.width; 1450 int h = pPix->drawable.height; 1451 int size = max(w, h); 1452 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1453 XAAPixmapCachePrivatePtr pCachePriv = 1454 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; 1455 XAACacheInfoPtr pCache, cacheRoot = NULL; 1456 int i, max = 0; 1457 int *current; 1458 1459 if(size <= 128) { 1460 if(pCachePriv->Info128) { 1461 cacheRoot = pCachePriv->Info128; 1462 max = pCachePriv->Num128x128; 1463 current = &pCachePriv->Current128; 1464 } else { 1465 cacheRoot = pCachePriv->InfoPartial; 1466 max = pCachePriv->NumPartial; 1467 current = &pCachePriv->CurrentPartial; 1468 } 1469 } else if(size <= 256) { 1470 cacheRoot = pCachePriv->Info256; 1471 max = pCachePriv->Num256x256; 1472 current = &pCachePriv->Current256; 1473 } else if(size <= 512) { 1474 cacheRoot = pCachePriv->Info512; 1475 max = pCachePriv->Num512x512; 1476 current = &pCachePriv->Current512; 1477 } else { /* something's wrong */ 1478 ErrorF("Something's wrong in XAACacheTile()\n"); 1479 return pCachePriv->Info128; 1480 } 1481 1482 pCache = cacheRoot; 1483 1484 /* lets look for it */ 1485 for(i = 0; i < max; i++, pCache++) { 1486 if(pCache->serialNumber == pPix->drawable.serialNumber) { 1487 pCache->trans_color = -1; 1488 return pCache; 1489 } 1490 } 1491 1492 pCache = &cacheRoot[(*current)++]; 1493 if(*current >= max) *current = 0; 1494 1495 pCache->serialNumber = pPix->drawable.serialNumber; 1496 pCache->trans_color = pCache->bg = pCache->fg = -1; 1497 pCache->orig_w = w; pCache->orig_h = h; 1498 (*infoRec->WritePixmapToCache)( 1499 pScrn, pCache->x, pCache->y, w, h, pPix->devPrivate.ptr, 1500 pPix->devKind, pPix->drawable.bitsPerPixel, pPix->drawable.depth); 1501 if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && 1502 ((w != pCache->w) || (h != pCache->h))) 1503 XAATileCache(pScrn, pCache, w, h); 1504 1505 return pCache; 1506} 1507 1508XAACacheInfoPtr 1509XAACacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) 1510{ 1511 int w = pPix->drawable.width; 1512 int h = pPix->drawable.height; 1513 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1514 XAAPixmapCachePrivatePtr pCachePriv = 1515 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; 1516 XAACacheInfoPtr pCache, cacheRoot = NULL; 1517 int i, max = 0, funcNo, pad, dwords, bpp = pScrn->bitsPerPixel; 1518 int *current; 1519 StippleScanlineProcPtr StippleFunc; 1520 unsigned char *data, *srcPtr, *dstPtr; 1521 1522 if((h <= 128) && (w <= 128 * bpp)) { 1523 if(pCachePriv->Info128) { 1524 cacheRoot = pCachePriv->Info128; 1525 max = pCachePriv->Num128x128; 1526 current = &pCachePriv->Current128; 1527 } else { 1528 cacheRoot = pCachePriv->InfoPartial; 1529 max = pCachePriv->NumPartial; 1530 current = &pCachePriv->CurrentPartial; 1531 } 1532 } else if((h <= 256) && (w <= 256 * bpp)){ 1533 cacheRoot = pCachePriv->Info256; 1534 max = pCachePriv->Num256x256; 1535 current = &pCachePriv->Current256; 1536 } else if((h <= 512) && (w <= 526 * bpp)){ 1537 cacheRoot = pCachePriv->Info512; 1538 max = pCachePriv->Num512x512; 1539 current = &pCachePriv->Current512; 1540 } else { /* something's wrong */ 1541 ErrorF("Something's wrong in XAACacheMonoStipple()\n"); 1542 return pCachePriv->Info128; 1543 } 1544 1545 pCache = cacheRoot; 1546 1547 /* lets look for it */ 1548 for(i = 0; i < max; i++, pCache++) { 1549 if((pCache->serialNumber == pPix->drawable.serialNumber) && 1550 (pCache->fg == -1) && (pCache->bg == -1)) { 1551 pCache->trans_color = -1; 1552 return pCache; 1553 } 1554 } 1555 1556 pCache = &cacheRoot[(*current)++]; 1557 if(*current >= max) *current = 0; 1558 1559 pCache->serialNumber = pPix->drawable.serialNumber; 1560 pCache->trans_color = pCache->bg = pCache->fg = -1; 1561 pCache->orig_w = w; pCache->orig_h = h; 1562 1563 if(w <= 32) { 1564 if(w & (w - 1)) funcNo = 1; 1565 else funcNo = 0; 1566 } else funcNo = 2; 1567 1568 pad = BitmapBytePad(pCache->w * bpp); 1569 dwords = bytes_to_int32(pad); 1570 dstPtr = data = (unsigned char*)malloc(pad * pCache->h); 1571 srcPtr = (unsigned char*)pPix->devPrivate.ptr; 1572 1573 if(infoRec->ScreenToScreenColorExpandFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) 1574 StippleFunc = XAAStippleScanlineFuncMSBFirst[funcNo]; 1575 else 1576 StippleFunc = XAAStippleScanlineFuncLSBFirst[funcNo]; 1577 1578 /* don't bother generating more than we'll ever use */ 1579 max = ((pScrn->displayWidth + w - 1) + 31) >> 5; 1580 if(dwords > max) 1581 dwords = max; 1582 1583 for(i = 0; i < h; i++) { 1584 (*StippleFunc)((CARD32*)dstPtr, (CARD32*)srcPtr, 0, w, dwords); 1585 srcPtr += pPix->devKind; 1586 dstPtr += pad; 1587 } 1588 1589 while((h<<1) <= pCache->h) { 1590 memcpy(data + (pad * h), data, pad * h); 1591 h <<= 1; 1592 } 1593 1594 if(h < pCache->h) 1595 memcpy(data + (pad * h), data, pad * (pCache->h - h)); 1596 1597 (*infoRec->WritePixmapToCache)( 1598 pScrn, pCache->x, pCache->y, pCache->w, pCache->h, data, 1599 pad, bpp, pScrn->depth); 1600 1601 free(data); 1602 1603 return pCache; 1604} 1605 1606XAACacheInfoPtr 1607XAACachePlanarMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) 1608{ 1609 int w = pPix->drawable.width; 1610 int h = pPix->drawable.height; 1611 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1612 XAAPixmapCachePrivatePtr pCachePriv = 1613 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; 1614 XAACacheInfoPtr pCache, cacheRoot = NULL; 1615 int i, max = 0; 1616 int *current; 1617 1618 if((h <= 128) && (w <= 128)) { 1619 if(pCachePriv->Info128) { 1620 cacheRoot = pCachePriv->Info128; 1621 max = pCachePriv->Num128x128; 1622 current = &pCachePriv->Current128; 1623 } else { 1624 cacheRoot = pCachePriv->InfoPartial; 1625 max = pCachePriv->NumPartial; 1626 current = &pCachePriv->CurrentPartial; 1627 } 1628 } else if((h <= 256) && (w <= 256)){ 1629 cacheRoot = pCachePriv->Info256; 1630 max = pCachePriv->Num256x256; 1631 current = &pCachePriv->Current256; 1632 } else if((h <= 512) && (w <= 526)){ 1633 cacheRoot = pCachePriv->Info512; 1634 max = pCachePriv->Num512x512; 1635 current = &pCachePriv->Current512; 1636 } else { /* something's wrong */ 1637 ErrorF("Something's wrong in XAACachePlanarMonoStipple()\n"); 1638 return pCachePriv->Info128; 1639 } 1640 1641 pCache = cacheRoot; 1642 1643 /* lets look for it */ 1644 for(i = 0; i < max; i++, pCache++) { 1645 if((pCache->serialNumber == pPix->drawable.serialNumber) && 1646 (pCache->fg == -1) && (pCache->bg == -1)) { 1647 pCache->trans_color = -1; 1648 return pCache; 1649 } 1650 } 1651 1652 pCache = &cacheRoot[(*current)++]; 1653 if(*current >= max) *current = 0; 1654 1655 pCache->serialNumber = pPix->drawable.serialNumber; 1656 pCache->trans_color = pCache->bg = pCache->fg = -1; 1657 pCache->orig_w = w; pCache->orig_h = h; 1658 1659 /* Plane 0 holds the stipple. Plane 1 holds the inverted stipple */ 1660 (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, 1661 pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr, 1662 pPix->devKind, 1, 2); 1663 if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_MONO_DATA) && 1664 ((w != pCache->w) || (h != pCache->h))) 1665 XAATileCache(pScrn, pCache, w, h); 1666 1667 return pCache; 1668} 1669 1670XAACachePlanarMonoStippleProc 1671XAAGetCachePlanarMonoStipple(void) 1672{ 1673 return XAACachePlanarMonoStipple; 1674} 1675 1676XAACacheInfoPtr 1677XAACacheStipple(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) 1678{ 1679 int w = pPix->drawable.width; 1680 int h = pPix->drawable.height; 1681 int size = max(w, h); 1682 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1683 XAAPixmapCachePrivatePtr pCachePriv = 1684 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; 1685 XAACacheInfoPtr pCache, cacheRoot = NULL; 1686 int i, max = 0; 1687 int *current; 1688 1689 if(size <= 128) { 1690 if(pCachePriv->Info128) { 1691 cacheRoot = pCachePriv->Info128; 1692 max = pCachePriv->Num128x128; 1693 current = &pCachePriv->Current128; 1694 } else { 1695 cacheRoot = pCachePriv->InfoPartial; 1696 max = pCachePriv->NumPartial; 1697 current = &pCachePriv->CurrentPartial; 1698 } 1699 } else if(size <= 256) { 1700 cacheRoot = pCachePriv->Info256; 1701 max = pCachePriv->Num256x256; 1702 current = &pCachePriv->Current256; 1703 } else if(size <= 512) { 1704 cacheRoot = pCachePriv->Info512; 1705 max = pCachePriv->Num512x512; 1706 current = &pCachePriv->Current512; 1707 } else { /* something's wrong */ 1708 ErrorF("Something's wrong in XAACacheStipple()\n"); 1709 return pCachePriv->Info128; 1710 } 1711 1712 pCache = cacheRoot; 1713 /* lets look for it */ 1714 if(bg == -1) 1715 for(i = 0; i < max; i++, pCache++) { 1716 if((pCache->serialNumber == pPix->drawable.serialNumber) && 1717 (fg == pCache->fg) && (pCache->fg != pCache->bg)) { 1718 pCache->trans_color = pCache->bg; 1719 return pCache; 1720 } 1721 } 1722 else 1723 for(i = 0; i < max; i++, pCache++) { 1724 if((pCache->serialNumber == pPix->drawable.serialNumber) && 1725 (fg == pCache->fg) && (bg == pCache->bg)) { 1726 pCache->trans_color = -1; 1727 return pCache; 1728 } 1729 } 1730 1731 pCache = &cacheRoot[(*current)++]; 1732 if(*current >= max) *current = 0; 1733 1734 pCache->serialNumber = pPix->drawable.serialNumber; 1735 pCache->fg = fg; 1736 if(bg == -1) 1737 pCache->trans_color = bg = fg ^ 1; 1738 else 1739 pCache->trans_color = -1; 1740 pCache->bg = bg; 1741 1742 pCache->orig_w = w; pCache->orig_h = h; 1743 (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, 1744 pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr, 1745 pPix->devKind, fg, bg); 1746 if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && 1747 ((w != pCache->w) || (h != pCache->h))) 1748 XAATileCache(pScrn, pCache, w, h); 1749 1750 return pCache; 1751} 1752 1753 1754 1755XAACacheInfoPtr 1756XAACacheMono8x8Pattern(ScrnInfoPtr pScrn, int pat0, int pat1) 1757{ 1758 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1759 XAAPixmapCachePrivatePtr pCachePriv = 1760 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; 1761 XAACacheInfoPtr pCache = pCachePriv->InfoMono; 1762 int i; 1763 1764 for(i = 0; i < pCachePriv->NumMono; i++, pCache++) { 1765 if(pCache->serialNumber && 1766 (pCache->pat0 == pat0) && (pCache->pat1 == pat1)) 1767 return pCache; 1768 } 1769 1770 /* OK, let's cache it */ 1771 pCache = &pCachePriv->InfoMono[pCachePriv->CurrentMono++]; 1772 if(pCachePriv->CurrentMono >= pCachePriv->NumMono) 1773 pCachePriv->CurrentMono = 0; 1774 1775 pCache->serialNumber = 1; /* we don't care since we do lookups by pattern */ 1776 pCache->pat0 = pat0; 1777 pCache->pat1 = pat1; 1778 1779 (*infoRec->WriteMono8x8PatternToCache)(pScrn, pCache); 1780 1781 return pCache; 1782} 1783 1784 1785 1786XAACacheInfoPtr 1787XAACacheColor8x8Pattern(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) 1788{ 1789 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1790 XAAPixmapCachePrivatePtr pCachePriv = 1791 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; 1792 XAACacheInfoPtr pCache = pCachePriv->InfoColor; 1793 XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); 1794 int i; 1795 1796 if(!(pixPriv->flags & REDUCIBLE_TO_2_COLOR)) { 1797 for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { 1798 if(pCache->serialNumber == pPix->drawable.serialNumber) { 1799 pCache->trans_color = -1; 1800 return pCache; 1801 } 1802 } 1803 pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; 1804 if(pCachePriv->CurrentColor >= pCachePriv->NumColor) 1805 pCachePriv->CurrentColor = 0; 1806 1807 pCache->serialNumber = pPix->drawable.serialNumber; 1808 pCache->trans_color = pCache->fg = pCache->bg = -1; 1809 } else { 1810 int pat0 = pixPriv->pattern0; 1811 int pat1 = pixPriv->pattern1; 1812 1813 if(fg == -1) { /* it's a tile */ 1814 fg = pixPriv->fg; bg = pixPriv->bg; 1815 } 1816 1817 if(bg == -1) { /* stipple */ 1818 for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { 1819 if(pCache->serialNumber && 1820 (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && 1821 (pCache->fg == fg) && (pCache->bg != fg)) { 1822 pCache->trans_color = pCache->bg; 1823 return pCache; 1824 } 1825 } 1826 } else { /* opaque stipple */ 1827 for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { 1828 if(pCache->serialNumber && 1829 (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && 1830 (pCache->fg == fg) && (pCache->bg == bg)) { 1831 pCache->trans_color = -1; 1832 return pCache; 1833 } 1834 } 1835 } 1836 pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; 1837 if(pCachePriv->CurrentColor >= pCachePriv->NumColor) 1838 pCachePriv->CurrentColor = 0; 1839 1840 if(bg == -1) 1841 pCache->trans_color = bg = fg ^ 1; 1842 else 1843 pCache->trans_color = -1; 1844 1845 pCache->pat0 = pat0; pCache->pat1 = pat1; 1846 pCache->fg = fg; pCache->bg = bg; 1847 pCache->serialNumber = 1; 1848 } 1849 1850 (*infoRec->WriteColor8x8PatternToCache)(pScrn, pPix, pCache); 1851 1852 return pCache; 1853} 1854 1855 1856void 1857XAAWriteBitmapToCache( 1858 ScrnInfoPtr pScrn, 1859 int x, int y, int w, int h, 1860 unsigned char *src, 1861 int srcwidth, 1862 int fg, int bg 1863) { 1864 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1865 1866 (*infoRec->WriteBitmap)(pScrn, x, y, w, h, src, srcwidth, 1867 0, fg, bg, GXcopy, ~0); 1868} 1869 1870void 1871XAAWriteBitmapToCacheLinear( 1872 ScrnInfoPtr pScrn, 1873 int x, int y, int w, int h, 1874 unsigned char *src, 1875 int srcwidth, 1876 int fg, int bg 1877){ 1878 ScreenPtr pScreen = pScrn->pScreen; 1879 PixmapPtr pScreenPix, pDstPix; 1880 ChangeGCVal gcvals[2]; 1881 GCPtr pGC; 1882 1883 pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); 1884 1885 pDstPix = GetScratchPixmapHeader(pScreen, pScreenPix->drawable.width, 1886 y + h, pScreenPix->drawable.depth, 1887 pScreenPix->drawable.bitsPerPixel, 1888 pScreenPix->devKind, 1889 pScreenPix->devPrivate.ptr); 1890 1891 pGC = GetScratchGC(pScreenPix->drawable.depth, pScreen); 1892 gcvals[0].val = fg; 1893 gcvals[1].val = bg; 1894 ChangeGC(NullClient, pGC, GCForeground | GCBackground, gcvals); 1895 ValidateGC((DrawablePtr)pDstPix, pGC); 1896 1897 /* We've unwrapped already so these ops miss a sync */ 1898 SYNC_CHECK(pScrn); 1899 1900 (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, 1, x, y, w, h, 0, 1901 XYBitmap, (pointer)src); 1902 1903 FreeScratchGC(pGC); 1904 FreeScratchPixmapHeader(pDstPix); 1905} 1906 1907 1908void 1909XAAWritePixmapToCache( 1910 ScrnInfoPtr pScrn, 1911 int x, int y, int w, int h, 1912 unsigned char *src, 1913 int srcwidth, 1914 int bpp, int depth 1915) { 1916 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1917 1918 (*infoRec->WritePixmap)(pScrn, x, y, w, h, src, srcwidth, 1919 GXcopy, ~0, -1, bpp, depth); 1920} 1921 1922 1923 1924void 1925XAAWritePixmapToCacheLinear( 1926 ScrnInfoPtr pScrn, 1927 int x, int y, int w, int h, 1928 unsigned char *src, 1929 int srcwidth, 1930 int bpp, int depth 1931){ 1932 ScreenPtr pScreen = pScrn->pScreen; 1933 PixmapPtr pScreenPix, pDstPix; 1934 GCPtr pGC; 1935 1936 pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); 1937 1938 pDstPix = GetScratchPixmapHeader(pScreen, x + w, y + h, 1939 depth, bpp, pScreenPix->devKind, 1940 pScreenPix->devPrivate.ptr); 1941 1942 pGC = GetScratchGC(depth, pScreen); 1943 ValidateGC((DrawablePtr)pDstPix, pGC); 1944 1945 /* We've unwrapped already so these ops miss a sync */ 1946 SYNC_CHECK(pScrn); 1947 1948 if(bpp == BitsPerPixel(depth)) 1949 (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, depth, x, y, w, 1950 h, 0, ZPixmap, (pointer)src); 1951 else { 1952 PixmapPtr pSrcPix; 1953 1954 pSrcPix = GetScratchPixmapHeader(pScreen, w, h, depth, bpp, 1955 srcwidth, (pointer)src); 1956 1957 (*pGC->ops->CopyArea)((DrawablePtr)pSrcPix, (DrawablePtr)pDstPix, 1958 pGC, 0, 0, w, h, x, y); 1959 1960 FreeScratchPixmapHeader(pSrcPix); 1961 } 1962 1963 FreeScratchGC(pGC); 1964 FreeScratchPixmapHeader(pDstPix); 1965} 1966 1967 1968void 1969XAAWriteMono8x8PatternToCache( 1970 ScrnInfoPtr pScrn, 1971 XAACacheInfoPtr pCache 1972){ 1973 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 1974 XAAPixmapCachePrivatePtr pCachePriv = 1975 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; 1976 unsigned char *data; 1977 int pad, Bpp = (pScrn->bitsPerPixel >> 3); 1978 1979 pCache->offsets = pCachePriv->MonoOffsets; 1980 1981 pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); 1982 1983 data = (unsigned char*)malloc(pad * pCache->h); 1984 if(!data) return; 1985 1986 if(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { 1987 CARD32* ptr = (CARD32*)data; 1988 ptr[0] = pCache->pat0; ptr[1] = pCache->pat1; 1989 } else { 1990 CARD32 *ptr; 1991 DDXPointPtr pPoint = pCache->offsets; 1992 int patx, paty, i; 1993 1994 for(i = 0; i < 64; i++, pPoint++) { 1995 patx = pCache->pat0; paty = pCache->pat1; 1996 XAARotateMonoPattern(&patx, &paty, i & 0x07, i >> 3, 1997 (infoRec->Mono8x8PatternFillFlags & 1998 BIT_ORDER_IN_BYTE_MSBFIRST)); 1999 ptr = (CARD32*)(data + (pad * pPoint->y) + (Bpp * pPoint->x)); 2000 ptr[0] = patx; ptr[1] = paty; 2001 } 2002 } 2003 2004 (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y, 2005 pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth); 2006 2007 free(data); 2008} 2009 2010void 2011XAAWriteColor8x8PatternToCache( 2012 ScrnInfoPtr pScrn, 2013 PixmapPtr pPix, 2014 XAACacheInfoPtr pCache 2015){ 2016 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); 2017 XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); 2018 XAAPixmapCachePrivatePtr pCachePriv = 2019 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; 2020 int pad, i, w, h, nw, nh, Bpp; 2021 unsigned char *data, *srcPtr, *dstPtr; 2022 2023 pCache->offsets = pCachePriv->ColorOffsets; 2024 2025 if(pixPriv->flags & REDUCIBLE_TO_2_COLOR) { 2026 CARD32* ptr; 2027 pad = BitmapBytePad(pCache->w); 2028 data = (unsigned char*)malloc(pad * pCache->h); 2029 if(!data) return; 2030 2031 if(infoRec->Color8x8PatternFillFlags & 2032 HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { 2033 ptr = (CARD32*)data; 2034 ptr[0] = pCache->pat0; ptr[1] = pCache->pat1; 2035 } else { 2036 int patx, paty; 2037 2038 ptr = (CARD32*)data; 2039 ptr[0] = ptr[2] = pCache->pat0; ptr[1] = ptr[3] = pCache->pat1; 2040 for(i = 1; i < 8; i++) { 2041 patx = pCache->pat0; paty = pCache->pat1; 2042 XAARotateMonoPattern(&patx, &paty, i, 0, 2043 (infoRec->Mono8x8PatternFillFlags & 2044 BIT_ORDER_IN_BYTE_MSBFIRST)); 2045 ptr = (CARD32*)(data + (pad * i)); 2046 ptr[0] = ptr[2] = patx; ptr[1] = ptr[3] = paty; 2047 } 2048 } 2049 2050 (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, 2051 pCache->w, pCache->h, data, pad, pCache->fg, pCache->bg); 2052 2053 free(data); 2054 return; 2055 } 2056 2057 Bpp = pScrn->bitsPerPixel >> 3; 2058 h = min(8,pPix->drawable.height); 2059 w = min(8,pPix->drawable.width); 2060 pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); 2061 2062 data = (unsigned char*)malloc(pad * pCache->h); 2063 if(!data) return; 2064 2065 /* Write and expand horizontally. */ 2066 for (i = h, dstPtr = data, srcPtr = pPix->devPrivate.ptr; i--; 2067 srcPtr += pPix->devKind, dstPtr += pScrn->bitsPerPixel) { 2068 nw = w; 2069 memcpy(dstPtr, srcPtr, w * Bpp); 2070 while (nw != 8) { 2071 memcpy(dstPtr + (nw * Bpp), dstPtr, nw * Bpp); 2072 nw <<= 1; 2073 } 2074 } 2075 nh = h; 2076 /* Expand vertically. */ 2077 while (nh != 8) { 2078 memcpy(data + (nh*pScrn->bitsPerPixel), data, nh*pScrn->bitsPerPixel); 2079 nh <<= 1; 2080 } 2081 2082 if(!(infoRec->Color8x8PatternFillFlags & 2083 HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){ 2084 int j; 2085 unsigned char *ptr = data + (128 * Bpp); 2086 2087 memcpy(data + (64 * Bpp), data, 64 * Bpp); 2088 for(i = 1; i < 8; i++, ptr += (128 * Bpp)) { 2089 for(j = 0; j < 8; j++) { 2090 memcpy(ptr + (j * 8) * Bpp, data + (j * 8 + i) * Bpp, 2091 (8 - i) * Bpp); 2092 memcpy(ptr + (j * 8 + 8 - i) * Bpp, data + j * 8 * Bpp, i*Bpp); 2093 } 2094 memcpy(ptr + (64 * Bpp), ptr, 64 * Bpp); 2095 } 2096 } 2097 2098 (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y, 2099 pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth); 2100 2101 free(data); 2102} 2103 2104 2105 2106int 2107XAAStippledFillChooser(GCPtr pGC) 2108{ 2109 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 2110 PixmapPtr pPixmap = pGC->stipple; 2111 XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); 2112 2113 if(!(pPriv->flags & REDUCIBILITY_CHECKED) && 2114 (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { 2115 XAACheckStippleReducibility(pPixmap); 2116 } 2117 2118 2119 if(pPriv->flags & REDUCIBLE_TO_8x8) { 2120 if(infoRec->CanDoMono8x8 && 2121 !(infoRec->FillMono8x8PatternSpansFlags & NO_TRANSPARENCY) && 2122 ((pGC->alu == GXcopy) || !(infoRec->FillMono8x8PatternSpansFlags & 2123 TRANSPARENCY_GXCOPY_ONLY)) && 2124 CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && 2125 CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && 2126 CHECK_FG(pGC,infoRec->FillMono8x8PatternSpansFlags) && 2127 CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { 2128 2129 return DO_MONO_8x8; 2130 } 2131 2132 if(infoRec->CanDoColor8x8 && 2133 !(infoRec->FillColor8x8PatternSpansFlags & NO_TRANSPARENCY) && 2134 ((pGC->alu == GXcopy) || !(infoRec->FillColor8x8PatternSpansFlags & 2135 TRANSPARENCY_GXCOPY_ONLY)) && 2136 CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && 2137 CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && 2138 CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { 2139 2140 return DO_COLOR_8x8; 2141 } 2142 } 2143 2144 if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && 2145 (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && 2146 (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / 2147 infoRec->CacheColorExpandDensity) && 2148 !(infoRec->FillCacheExpandSpansFlags & NO_TRANSPARENCY) && 2149 ((pGC->alu == GXcopy) || !(infoRec->FillCacheExpandSpansFlags & 2150 TRANSPARENCY_GXCOPY_ONLY)) && 2151 CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) && 2152 CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) && 2153 CHECK_FG(pGC,infoRec->FillCacheExpandSpansFlags) && 2154 CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) { 2155 2156 return DO_CACHE_EXPAND; 2157 } 2158 2159 2160 if(infoRec->UsingPixmapCache && 2161 !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && 2162 infoRec->FillCacheBltSpans && 2163 (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && 2164 (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && 2165 !(infoRec->FillCacheBltSpansFlags & NO_TRANSPARENCY) && 2166 ((pGC->alu == GXcopy) || !(infoRec->FillCacheBltSpansFlags & 2167 TRANSPARENCY_GXCOPY_ONLY)) && 2168 CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && 2169 CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && 2170 CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { 2171 2172 return DO_CACHE_BLT; 2173 } 2174 2175 if(infoRec->FillColorExpandSpans && 2176 !(infoRec->FillColorExpandSpansFlags & NO_TRANSPARENCY) && 2177 ((pGC->alu == GXcopy) || !(infoRec->FillColorExpandSpansFlags & 2178 TRANSPARENCY_GXCOPY_ONLY)) && 2179 CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) && 2180 CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) && 2181 CHECK_FG(pGC,infoRec->FillColorExpandSpansFlags) && 2182 CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) { 2183 2184 return DO_COLOR_EXPAND; 2185 } 2186 2187 return 0; 2188} 2189 2190 2191int 2192XAAOpaqueStippledFillChooser(GCPtr pGC) 2193{ 2194 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 2195 PixmapPtr pPixmap = pGC->stipple; 2196 XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); 2197 2198 if(XAA_DEPTH_BUG(pGC)) 2199 return 0; 2200 2201 if(!(pPriv->flags & REDUCIBILITY_CHECKED) && 2202 (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { 2203 XAACheckStippleReducibility(pPixmap); 2204 } 2205 2206 if(pPriv->flags & REDUCIBLE_TO_8x8) { 2207 if(infoRec->CanDoMono8x8 && 2208 !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && 2209 CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && 2210 CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && 2211 CHECK_COLORS(pGC,infoRec->FillMono8x8PatternSpansFlags) && 2212 CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { 2213 2214 return DO_MONO_8x8; 2215 } 2216 2217 if(infoRec->CanDoColor8x8 && 2218 CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && 2219 CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && 2220 CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { 2221 2222 return DO_COLOR_8x8; 2223 } 2224 } 2225 2226 if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && 2227 (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && 2228 (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / 2229 infoRec->CacheColorExpandDensity) && 2230 !(infoRec->FillCacheExpandSpansFlags & TRANSPARENCY_ONLY) && 2231 CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) && 2232 CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) && 2233 CHECK_COLORS(pGC,infoRec->FillCacheExpandSpansFlags) && 2234 CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) { 2235 2236 return DO_CACHE_EXPAND; 2237 } 2238 2239 if(infoRec->UsingPixmapCache && 2240 !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && 2241 infoRec->FillCacheBltSpans && 2242 (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && 2243 (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && 2244 CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && 2245 CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && 2246 CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { 2247 2248 return DO_CACHE_BLT; 2249 } 2250 2251 if(infoRec->FillColorExpandSpans && 2252 !(infoRec->FillColorExpandSpansFlags & TRANSPARENCY_ONLY) && 2253 CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) && 2254 CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) && 2255 CHECK_COLORS(pGC,infoRec->FillColorExpandSpansFlags) && 2256 CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) { 2257 2258 return DO_COLOR_EXPAND; 2259 } 2260 2261 return 0; 2262} 2263 2264 2265 2266int 2267XAATiledFillChooser(GCPtr pGC) 2268{ 2269 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); 2270 PixmapPtr pPixmap = pGC->tile.pixmap; 2271 XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); 2272 2273 if(IS_OFFSCREEN_PIXMAP(pPixmap) && infoRec->FillCacheBltSpans && 2274 CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && 2275 CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && 2276 CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { 2277 2278 return DO_PIXMAP_COPY; 2279 } 2280 2281 if(!(pPriv->flags & REDUCIBILITY_CHECKED) && 2282 (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { 2283 XAACheckTileReducibility(pPixmap,infoRec->CanDoMono8x8); 2284 } 2285 2286 if(pPriv->flags & REDUCIBLE_TO_8x8) { 2287 if((pPriv->flags & REDUCIBLE_TO_2_COLOR) && infoRec->CanDoMono8x8 && 2288 !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && 2289 CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && 2290 CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && 2291 (!(infoRec->FillMono8x8PatternSpansFlags & RGB_EQUAL) || 2292 (CHECK_RGB_EQUAL(pPriv->fg) && CHECK_RGB_EQUAL(pPriv->bg))) && 2293 CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { 2294 2295 return DO_MONO_8x8; 2296 } 2297 2298 if(infoRec->CanDoColor8x8 && 2299 CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && 2300 CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && 2301 CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { 2302 2303 return DO_COLOR_8x8; 2304 } 2305 } 2306 2307 if(infoRec->UsingPixmapCache && infoRec->FillCacheBltSpans && 2308 (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && 2309 (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && 2310 CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && 2311 CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && 2312 CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { 2313 2314 return DO_CACHE_BLT; 2315 } 2316 2317 if(infoRec->FillImageWriteRects && 2318 CHECK_NO_GXCOPY(pGC,infoRec->FillImageWriteRectsFlags) && 2319 CHECK_ROP(pGC,infoRec->FillImageWriteRectsFlags) && 2320 CHECK_ROPSRC(pGC,infoRec->FillImageWriteRectsFlags) && 2321 CHECK_PLANEMASK(pGC,infoRec->FillImageWriteRectsFlags)) { 2322 2323 return DO_IMAGE_WRITE; 2324 } 2325 2326 return 0; 2327} 2328 2329 2330static int RotateMasksX[8] = { 2331 0xFFFFFFFF, 0x7F7F7F7F, 0x3F3F3F3F, 0x1F1F1F1F, 2332 0x0F0F0F0F, 0x07070707, 0x03030303, 0x01010101 2333}; 2334 2335static int RotateMasksY[4] = { 2336 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF 2337}; 2338 2339void 2340XAARotateMonoPattern( 2341 int *pat0, int *pat1, 2342 int xorg, int yorg, 2343 Bool msbfirst 2344){ 2345 int tmp, mask; 2346 2347 if(xorg) { 2348 if(msbfirst) xorg = 8 - xorg; 2349 mask = RotateMasksX[xorg]; 2350 *pat0 = ((*pat0 >> xorg) & mask) | ((*pat0 << (8 - xorg)) & ~mask); 2351 *pat1 = ((*pat1 >> xorg) & mask) | ((*pat1 << (8 - xorg)) & ~mask); 2352 } 2353 if(yorg >= 4) { 2354 tmp = *pat0; *pat0 = *pat1; *pat1 = tmp; 2355 yorg -= 4; 2356 } 2357 if(yorg) { 2358 mask = RotateMasksY[yorg]; 2359 yorg <<= 3; 2360 tmp = *pat0; 2361 *pat0 = ((*pat0 >> yorg) & mask) | ((*pat1 << (32 - yorg)) & ~mask); 2362 *pat1 = ((*pat1 >> yorg) & mask) | ((tmp << (32 - yorg)) & ~mask); 2363 } 2364} 2365 2366 2367 2368void 2369XAAInvalidatePixmapCache(ScreenPtr pScreen) 2370{ 2371 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); 2372 XAAPixmapCachePrivatePtr pCachePriv = 2373 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; 2374 int i; 2375 2376 if(!pCachePriv) return; 2377 2378 for(i = 0; i < pCachePriv->Num512x512; i++) 2379 (pCachePriv->Info512)[i].serialNumber = 0; 2380 for(i = 0; i < pCachePriv->Num256x256; i++) 2381 (pCachePriv->Info256)[i].serialNumber = 0; 2382 for(i = 0; i < pCachePriv->Num128x128; i++) 2383 (pCachePriv->Info128)[i].serialNumber = 0; 2384 for(i = 0; i < pCachePriv->NumPartial; i++) 2385 (pCachePriv->InfoPartial)[i].serialNumber = 0; 2386 for(i = 0; i < pCachePriv->NumMono; i++) 2387 (pCachePriv->InfoMono)[i].serialNumber = 0; 2388 for(i = 0; i < pCachePriv->NumColor; i++) 2389 (pCachePriv->InfoColor)[i].serialNumber = 0; 2390} 2391