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