Home | History | Annotate | Line # | Download | only in xaa
      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 
     33 static int CacheInitIndex = -1;
     34 #define CACHEINIT(p) ((p)->privates[CacheInitIndex].val)
     35 
     36 
     37 typedef struct _CacheLink {
     38    int x;
     39    int y;
     40    int w;
     41    int h;
     42    struct _CacheLink *next;
     43 } CacheLink, *CacheLinkPtr;
     44 
     45 
     46 static void
     47 TransferList(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 
     63 static CacheLinkPtr
     64 Enlist(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 
     77 static CacheLinkPtr
     78 Delist(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 
     90 static void
     91 FreeList(CacheLinkPtr link) {
     92     CacheLinkPtr tmp;
     93 
     94     while(link) {
     95 	tmp = link;
     96 	link = link->next;
     97 	free(tmp);
     98     }
     99 }
    100 
    101 
    102 
    103 static CacheLinkPtr
    104 QuadLinks(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 
    126 static void
    127 SubdivideList(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 
    142 static void
    143 FreePixmapCachePrivate(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 
    157 void
    158 XAAClosePixmapCache(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 
    171 static CacheLinkPtr
    172 ThinOutPartials(
    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 
    255 GOT_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 
    284 static void
    285 ConvertColorToMono(
    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 
    303 static void
    304 ConvertAllPartialsTo8x8(
    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 
    369 static CacheLinkPtr
    370 ExtractOneThatFits(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 
    395 static CacheLinkPtr
    396 ConvertSomePartialsTo8x8(
    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 
    587 GOT_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 
    627 void
    628 XAAInitPixmapCache(
    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
   1079 static CARD32 StippleMasks[4] = {
   1080    0x80808080,
   1081    0xC0C0C0C0,
   1082    0x00000000,
   1083    0xF0F0F0F0
   1084 };
   1085 #else
   1086 static CARD32 StippleMasks[4] = {
   1087    0x01010101,
   1088    0x03030303,
   1089    0x00000000,
   1090    0x0F0F0F0F
   1091 };
   1092 #endif
   1093 
   1094 Bool
   1095 XAACheckStippleReducibility(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 
   1191 static inline CARD32
   1192 load_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 
   1208 Bool
   1209 XAACheckTileReducibility(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 
   1414 void 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 
   1446 XAACacheInfoPtr
   1447 XAACacheTile(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 
   1508 XAACacheInfoPtr
   1509 XAACacheMonoStipple(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 
   1606 XAACacheInfoPtr
   1607 XAACachePlanarMonoStipple(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 
   1670 XAACachePlanarMonoStippleProc
   1671 XAAGetCachePlanarMonoStipple(void)
   1672 {
   1673     return XAACachePlanarMonoStipple;
   1674 }
   1675 
   1676 XAACacheInfoPtr
   1677 XAACacheStipple(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 
   1755 XAACacheInfoPtr
   1756 XAACacheMono8x8Pattern(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 
   1786 XAACacheInfoPtr
   1787 XAACacheColor8x8Pattern(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 
   1856 void
   1857 XAAWriteBitmapToCache(
   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 
   1870 void
   1871 XAAWriteBitmapToCacheLinear(
   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 
   1908 void
   1909 XAAWritePixmapToCache(
   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 
   1924 void
   1925 XAAWritePixmapToCacheLinear(
   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 
   1968 void
   1969 XAAWriteMono8x8PatternToCache(
   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 
   2010 void
   2011 XAAWriteColor8x8PatternToCache(
   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 
   2106 int
   2107 XAAStippledFillChooser(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 
   2191 int
   2192 XAAOpaqueStippledFillChooser(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 
   2266 int
   2267 XAATiledFillChooser(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 
   2330 static int RotateMasksX[8] = {
   2331    0xFFFFFFFF, 0x7F7F7F7F, 0x3F3F3F3F, 0x1F1F1F1F,
   2332    0x0F0F0F0F, 0x07070707, 0x03030303, 0x01010101
   2333 };
   2334 
   2335 static int RotateMasksY[4] = {
   2336    0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF
   2337 };
   2338 
   2339 void
   2340 XAARotateMonoPattern(
   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 
   2368 void
   2369 XAAInvalidatePixmapCache(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