First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / xaa / xaaPCache.c
blob441788cd80f6be933f93968846c955676337a21a
2 #ifdef HAVE_XORG_CONFIG_H
3 #include <xorg-config.h>
4 #endif
6 #include <string.h>
8 #include "misc.h"
9 #include "xf86.h"
10 #include "xf86_OSproc.h"
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"
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
33 static int CacheInitIndex = -1;
34 #define CACHEINIT(p) ((p)->privates[CacheInitIndex].val)
37 typedef struct _CacheLink {
38 int x;
39 int y;
40 int w;
41 int h;
42 struct _CacheLink *next;
43 } CacheLink, *CacheLinkPtr;
46 static void
47 TransferList(CacheLinkPtr list, XAACacheInfoPtr array, int num)
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++;
63 static CacheLinkPtr
64 Enlist(CacheLinkPtr link, int x, int y, int w, int h)
66 CacheLinkPtr newLink;
68 newLink = xalloc(sizeof(CacheLink));
69 newLink->next = link;
70 newLink->x = x; newLink->y = y;
71 newLink->w = w; newLink->h = h;
72 return newLink;
77 static CacheLinkPtr
78 Delist(CacheLinkPtr link) {
79 CacheLinkPtr ret = NULL;
81 if(link) {
82 ret = link->next;
83 xfree(link);
85 return ret;
90 static void
91 FreeList(CacheLinkPtr link) {
92 CacheLinkPtr tmp;
94 while(link) {
95 tmp = link;
96 link = link->next;
97 xfree(tmp);
103 static CacheLinkPtr
104 QuadLinks(CacheLinkPtr big, CacheLinkPtr little)
106 /* CAUTION: This doesn't free big */
107 int w1, w2, h1, h2;
109 while(big) {
110 w1 = big->w >> 1;
111 w2 = big->w - w1;
112 h1 = big->h >> 1;
113 h2 = big->h - h1;
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);
120 big = big->next;
122 return little;
126 static void
127 SubdivideList(CacheLinkPtr *large, CacheLinkPtr *small)
129 CacheLinkPtr big = *large;
130 CacheLinkPtr little = *small;
131 int size = big->w >> 1;
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;
142 static void
143 FreePixmapCachePrivate(XAAPixmapCachePrivatePtr pPriv)
145 if(!pPriv) return;
147 if(pPriv->Info512)
148 xfree(pPriv->Info512);
149 if(pPriv->Info256)
150 xfree(pPriv->Info256);
151 if(pPriv->Info128)
152 xfree(pPriv->Info128);
153 if(pPriv->InfoColor)
154 xfree(pPriv->InfoColor);
155 if(pPriv->InfoMono)
156 xfree(pPriv->InfoMono);
157 if(pPriv->InfoPartial)
158 xfree(pPriv->InfoPartial);
160 xfree(pPriv);
163 void
164 XAAClosePixmapCache(ScreenPtr pScreen)
166 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
168 if(infoRec->PixmapCachePrivate)
169 FreePixmapCachePrivate(
170 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate);
172 infoRec->PixmapCachePrivate = NULL;
177 static CacheLinkPtr
178 ThinOutPartials(
179 CacheLinkPtr ListPartial,
180 int *num, int *maxw, int *maxh
181 ) {
182 /* This guy's job is to get at least 4 big slots out of a list of fragments */
184 CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers;
185 int Num64, Num32, Num16, Num8, NumKeepers;
186 int w, h;
188 List64 = List32 = List16 = List8 = ListKeepers = NULL;
189 Num64 = Num32 = Num16 = Num8 = NumKeepers = 0;
190 w = h = 0;
192 /* We sort partials by how large a square tile they can cache.
193 If a partial can't store a 64x64, 32x32, 16x16 or 8x8 tile,
194 we free it. */
196 pCur = ListPartial;
197 while(pCur) {
198 next = pCur->next;
199 if((pCur->w >= 64) && (pCur->h >= 64)) {
200 pCur->next = List64; List64 = pCur;
201 Num64++;
202 } else
203 if((pCur->w >= 32) && (pCur->h >= 32)) {
204 pCur->next = List32; List32 = pCur;
205 Num32++;
206 } else
207 if((pCur->w >= 16) && (pCur->h >= 16)) {
208 pCur->next = List16; List16 = pCur;
209 Num16++;
210 } else
211 if((pCur->w >= 8) && (pCur->h >= 8)) {
212 pCur->next = List8; List8 = pCur;
213 Num8++;
214 } else {
215 xfree(pCur);
218 pCur = next;
221 /* We save all the tiles from the largest bin that we can get
222 at least 4 of. If there are too few of a bigger slot, we
223 cut it in fourths to make smaller slots. */
225 if(Num64 >= 4) {
226 ListKeepers = List64; List64 = NULL;
227 NumKeepers = Num64;
228 goto GOT_EM;
229 } else if(Num64) {
230 List32 = QuadLinks(List64, List32);
231 Num32 += Num64 * 4;
232 Num64 = 0;
235 if(Num32 >= 4) {
236 ListKeepers = List32; List32 = NULL;
237 NumKeepers = Num32;
238 goto GOT_EM;
239 } else if(Num32) {
240 List16 = QuadLinks(List32, List16);
241 Num16 += Num32 * 4;
242 Num32 = 0;
245 if(Num16 >= 4) {
246 ListKeepers = List16; List16 = NULL;
247 NumKeepers = Num16;
248 goto GOT_EM;
249 } else if(Num16) {
250 List8 = QuadLinks(List16, List8);
251 Num8 += Num16 * 4;
252 Num16 = 0;
255 if(Num8 >= 4) {
256 ListKeepers = List8; List8 = NULL;
257 NumKeepers = Num8;
258 goto GOT_EM;
261 GOT_EM:
263 /* Free the ones we aren't using */
265 if(List64) FreeList(List64);
266 if(List32) FreeList(List32);
267 if(List16) FreeList(List16);
268 if(List8) FreeList(List8);
271 /* Enlarge the slots if we can */
273 if(ListKeepers) {
274 CacheLinkPtr pLink = ListKeepers;
275 w = h = 128;
277 while(pLink) {
278 if(pLink->w < w) w = pLink->w;
279 if(pLink->h < h) h = pLink->h;
280 pLink = pLink->next;
284 *maxw = w;
285 *maxh = h;
286 *num = NumKeepers;
287 return ListKeepers;
290 static void
291 ConvertColorToMono(
292 CacheLinkPtr *ColorList,
293 int ColorW, int ColorH,
294 CacheLinkPtr *MonoList,
295 int MonoW, int MonoH
297 int x, y, w;
299 x = (*ColorList)->x; y = (*ColorList)->y;
300 *ColorList = Delist(*ColorList);
302 while(ColorH) {
303 ColorH -= MonoH;
304 for(w = 0; w <= (ColorW - MonoW); w += MonoW)
305 *MonoList = Enlist(*MonoList, x + w, y + ColorH, MonoW, MonoH);
309 static void
310 ConvertAllPartialsTo8x8(
311 int *NumMono, int *NumColor,
312 CacheLinkPtr ListPartial,
313 CacheLinkPtr *ListMono,
314 CacheLinkPtr *ListColor,
315 XAAInfoRecPtr infoRec
317 /* This guy extracts as many 8x8 slots as it can out of fragments */
319 int ColorH = infoRec->CacheHeightColor8x8Pattern;
320 int ColorW = infoRec->CacheWidthColor8x8Pattern;
321 int MonoH = infoRec->CacheHeightMono8x8Pattern;
322 int MonoW = infoRec->CacheWidthMono8x8Pattern;
323 int x, y, w, Height, Width;
324 Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8);
325 Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8);
326 CacheLinkPtr pLink = ListPartial;
327 CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor;
329 if(DoColor && DoMono) {
330 /* we assume color patterns take more space than color ones */
331 if(MonoH > ColorH) ColorH = MonoH;
332 if(MonoW > ColorW) ColorW = MonoW;
335 /* Break up the area into as many Color and Mono slots as we can */
337 while(pLink) {
338 Height = pLink->h;
339 Width = pLink->w;
340 x = pLink->x;
341 y = pLink->y;
343 if(DoColor) {
344 while(Height >= ColorH) {
345 Height -= ColorH;
346 for(w = 0; w <= (Width - ColorW); w += ColorW) {
347 ColorList = Enlist(
348 ColorList, x + w, y + Height, ColorW, ColorH);
349 (*NumColor)++;
354 if(DoMono && (Height >= MonoH)) {
355 while(Height >= MonoH) {
356 Height -= MonoH;
357 for(w = 0; w <= (Width - MonoW); w += MonoW) {
358 MonoList = Enlist(
359 MonoList, x + w, y + Height, MonoW, MonoH);
360 (*NumMono)++;
365 pLink = pLink->next;
369 *ListMono = MonoList;
370 *ListColor = ColorList;
371 FreeList(ListPartial);
375 static CacheLinkPtr
376 ExtractOneThatFits(CacheLinkPtr *initList, int w, int h)
378 CacheLinkPtr list = *initList;
379 CacheLinkPtr prev = NULL;
381 while(list) {
382 if((list->w >= w) && (list->h >= h))
383 break;
384 prev = list;
385 list = list->next;
388 if(list) {
389 if(prev)
390 prev->next = list->next;
391 else
392 *initList = list->next;
394 list->next = NULL;
397 return list;
401 static CacheLinkPtr
402 ConvertSomePartialsTo8x8(
403 int *NumMono, int *NumColor, int *NumPartial,
404 CacheLinkPtr ListPartial,
405 CacheLinkPtr *ListMono,
406 CacheLinkPtr *ListColor,
407 int *maxw, int *maxh,
408 XAAInfoRecPtr infoRec
410 /* This guy tries to get 4 of each type of 8x8 slot requested out of
411 a list of fragments all while trying to retain some big fragments
412 for the cache blits */
414 int ColorH = infoRec->CacheHeightColor8x8Pattern;
415 int ColorW = infoRec->CacheWidthColor8x8Pattern;
416 int MonoH = infoRec->CacheHeightMono8x8Pattern;
417 int MonoW = infoRec->CacheWidthMono8x8Pattern;
418 Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8);
419 Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8);
420 CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers;
421 CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor;
422 int Num64, Num32, Num16, Num8, NumKeepers;
423 int w, h, Width, Height;
424 int MonosPerColor = 1;
426 if(DoColor && DoMono) {
427 /* we assume color patterns take more space than color ones */
428 if(MonoH > ColorH) ColorH = MonoH;
429 if(MonoW > ColorW) ColorW = MonoW;
430 MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW);
433 List64 = List32 = List16 = List8 = ListKeepers = MonoList = ColorList = NULL;
434 Num64 = Num32 = Num16 = Num8 = NumKeepers = 0;
435 Width = Height = 0;
437 /* We sort partials by how large a square tile they can cache.
438 We make 8x8 patterns from the leftovers if we can. */
440 pCur = ListPartial;
441 while(pCur) {
442 next = pCur->next;
443 if((pCur->w >= 64) && (pCur->h >= 64)) {
444 pCur->next = List64; List64 = pCur;
445 Num64++;
446 } else
447 if((pCur->w >= 32) && (pCur->h >= 32)) {
448 pCur->next = List32; List32 = pCur;
449 Num32++;
450 } else
451 if((pCur->w >= 16) && (pCur->h >= 16)) {
452 pCur->next = List16; List16 = pCur;
453 Num16++;
454 } else
455 if((pCur->w >= 8) && (pCur->h >= 8)) {
456 pCur->next = List8; List8 = pCur;
457 Num8++;
458 } else {
459 h = pCur->h;
460 if(DoColor && (pCur->w >= ColorW) && (h >= ColorH)) {
461 while(h >= ColorH) {
462 h -= ColorH;
463 for(w = 0; w <= (pCur->w - ColorW); w += ColorW) {
464 ColorList = Enlist( ColorList,
465 pCur->x + w, pCur->y + h, ColorW, ColorH);
466 (*NumColor)++;
470 if(DoMono && (pCur->w >= MonoW) && (h >= MonoH)) {
471 while(h >= MonoH) {
472 h -= MonoH;
473 for(w = 0; w <= (pCur->w - MonoW); w += MonoW) {
474 MonoList = Enlist( MonoList,
475 pCur->x + w, pCur->y + h, MonoW, MonoH);
476 (*NumMono)++;
480 xfree(pCur);
483 pCur = next;
486 /* Try to extract at least 4 of each type of 8x8 slot that we need */
488 if(DoColor) {
489 CacheLinkPtr theOne;
490 while(*NumColor < 4) {
491 theOne = NULL;
492 if(Num8) {
493 if((theOne = ExtractOneThatFits(&List8, ColorW, ColorH)))
494 Num8--;
496 if(Num16 && !theOne) {
497 if((theOne = ExtractOneThatFits(&List16, ColorW, ColorH)))
498 Num16--;
500 if(Num32 && !theOne) {
501 if((theOne = ExtractOneThatFits(&List32, ColorW, ColorH)))
502 Num32--;
504 if(Num64 && !theOne) {
505 if((theOne = ExtractOneThatFits(&List64, ColorW, ColorH)))
506 Num64--;
509 if(!theOne) break;
512 ConvertAllPartialsTo8x8(NumMono, NumColor, theOne,
513 &MonoList, &ColorList, infoRec);
515 if(DoMono) {
516 while(*NumColor && (*NumMono < 4)) {
517 ConvertColorToMono(&ColorList, ColorW, ColorH,
518 &MonoList, MonoW, MonoH);
519 (*NumColor)--; *NumMono += MonosPerColor;
525 if(DoMono) {
526 CacheLinkPtr theOne;
527 while(*NumMono < 4) {
528 theOne = NULL;
529 if(Num8) {
530 if((theOne = ExtractOneThatFits(&List8, MonoW, MonoH)))
531 Num8--;
533 if(Num16 && !theOne) {
534 if((theOne = ExtractOneThatFits(&List16, MonoW, MonoH)))
535 Num16--;
537 if(Num32 && !theOne) {
538 if((theOne = ExtractOneThatFits(&List32, MonoW, MonoH)))
539 Num32--;
541 if(Num64 && !theOne) {
542 if((theOne = ExtractOneThatFits(&List64, MonoW, MonoH)))
543 Num64--;
546 if(!theOne) break;
548 ConvertAllPartialsTo8x8(NumMono, NumColor, theOne,
549 &MonoList, &ColorList, infoRec);
553 /* We save all the tiles from the largest bin that we can get
554 at least 4 of. If there are too few of a bigger slot, we
555 cut it in fourths to make smaller slots. */
557 if(Num64 >= 4) {
558 ListKeepers = List64; List64 = NULL;
559 NumKeepers = Num64;
560 goto GOT_EM;
561 } else if(Num64) {
562 List32 = QuadLinks(List64, List32);
563 Num32 += Num64 * 4;
564 Num64 = 0;
567 if(Num32 >= 4) {
568 ListKeepers = List32; List32 = NULL;
569 NumKeepers = Num32;
570 goto GOT_EM;
571 } else if(Num32) {
572 List16 = QuadLinks(List32, List16);
573 Num16 += Num32 * 4;
574 Num32 = 0;
577 if(Num16 >= 4) {
578 ListKeepers = List16; List16 = NULL;
579 NumKeepers = Num16;
580 goto GOT_EM;
581 } else if(Num16) {
582 List8 = QuadLinks(List16, List8);
583 Num8 += Num16 * 4;
584 Num16 = 0;
587 if(Num8 >= 4) {
588 ListKeepers = List8; List8 = NULL;
589 NumKeepers = Num8;
590 goto GOT_EM;
593 GOT_EM:
595 /* Free the ones we aren't using */
597 if(List64)
598 ConvertAllPartialsTo8x8(NumMono, NumColor, List64,
599 &MonoList, &ColorList, infoRec);
600 if(List32)
601 ConvertAllPartialsTo8x8(NumMono, NumColor, List32,
602 &MonoList, &ColorList, infoRec);
603 if(List16)
604 ConvertAllPartialsTo8x8(NumMono, NumColor, List16,
605 &MonoList, &ColorList, infoRec);
606 if(List8)
607 ConvertAllPartialsTo8x8(NumMono, NumColor, List8,
608 &MonoList, &ColorList, infoRec);
611 /* Enlarge the slots if we can */
613 if(ListKeepers) {
614 CacheLinkPtr pLink = ListKeepers;
615 Width = Height = 128;
617 while(pLink) {
618 if(pLink->w < Width) Width = pLink->w;
619 if(pLink->h < Height) Height = pLink->h;
620 pLink = pLink->next;
624 *ListMono = MonoList;
625 *ListColor = ColorList;
626 *maxw = Width;
627 *maxh = Height;
628 *NumPartial = NumKeepers;
629 return ListKeepers;
633 void
634 XAAInitPixmapCache(
635 ScreenPtr pScreen,
636 RegionPtr areas,
637 pointer data
639 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
640 XAAInfoRecPtr infoRec = (XAAInfoRecPtr)data;
641 XAAPixmapCachePrivatePtr pCachePriv;
642 BoxPtr pBox = REGION_RECTS(areas);
643 int nBox = REGION_NUM_RECTS(areas);
644 int Num512, Num256, Num128, NumPartial, NumColor, NumMono;
645 int Target512, Target256;
646 CacheLinkPtr List512, List256, List128, ListPartial, ListColor, ListMono;
647 int x, y, w, h, ntotal, granularity, width, height, i;
648 int MaxPartialWidth, MaxPartialHeight;
650 infoRec->MaxCacheableTileWidth = 0;
651 infoRec->MaxCacheableTileHeight = 0;
652 infoRec->MaxCacheableStippleHeight = 0;
653 infoRec->MaxCacheableStippleWidth = 0;
654 infoRec->UsingPixmapCache = FALSE;
657 if(!nBox || !pBox || !(infoRec->Flags & PIXMAP_CACHE))
658 return;
660 /* Allocate a persistent per-screen init flag to control messages */
661 if (CacheInitIndex < 0)
662 CacheInitIndex = xf86AllocateScrnInfoPrivateIndex();
664 /* free the old private data if it exists */
665 if(infoRec->PixmapCachePrivate) {
666 FreePixmapCachePrivate(
667 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate);
668 infoRec->PixmapCachePrivate = NULL;
671 Num512 = Num256 = Num128 = NumPartial = NumMono = NumColor = 0;
672 List512 = List256 = List128 = ListPartial = ListMono = ListColor = NULL;
673 granularity = infoRec->CachePixelGranularity;
674 if(granularity <= 1) granularity = 0;
676 /* go through the boxes and break it into as many pieces as we can fit */
678 while(nBox--) {
679 x = pBox->x1;
680 if(granularity) {
681 int tmp = x % granularity;
682 if(tmp) x += (granularity - tmp);
684 width = pBox->x2 - x;
685 if(width <= 0) {pBox++; continue;}
687 y = pBox->y1;
688 height = pBox->y2 - y;
690 for(h = 0; h <= (height - 512); h += 512) {
691 for(w = 0; w <= (width - 512); w += 512) {
692 List512 = Enlist(List512, x + w, y + h, 512, 512);
693 Num512++;
695 for(; w <= (width - 256); w += 256) {
696 List256 = Enlist(List256, x + w, y + h, 256, 256);
697 List256 = Enlist(List256, x + w, y + h + 256, 256, 256);
698 Num256 += 2;
700 for(; w <= (width - 128); w += 128) {
701 List128 = Enlist(List128, x + w, y + h, 128, 128);
702 List128 = Enlist(List128, x + w, y + h + 128, 128, 128);
703 List128 = Enlist(List128, x + w, y + h + 256, 128, 128);
704 List128 = Enlist(List128, x + w, y + h + 384, 128, 128);
705 Num128 += 4;
707 if(w < width) {
708 int d = width - w;
709 ListPartial = Enlist(ListPartial, x + w, y + h, d, 128);
710 ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128);
711 ListPartial = Enlist(ListPartial, x + w, y + h + 256, d, 128);
712 ListPartial = Enlist(ListPartial, x + w, y + h + 384, d, 128);
713 NumPartial += 4;
716 for(; h <= (height - 256); h += 256) {
717 for(w = 0; w <= (width - 256); w += 256) {
718 List256 = Enlist(List256, x + w, y + h, 256, 256);
719 Num256++;
721 for(; w <= (width - 128); w += 128) {
722 List128 = Enlist(List128, x + w, y + h, 128, 128);
723 List128 = Enlist(List128, x + w, y + h + 128, 128, 128);
724 Num128 += 2;
726 if(w < width) {
727 int d = width - w;
728 ListPartial = Enlist(ListPartial, x + w, y + h, d, 128);
729 ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128);
730 NumPartial += 2;
733 for(; h <= (height - 128); h += 128) {
734 for(w = 0; w <= (width - 128); w += 128) {
735 List128 = Enlist(List128, x + w, y + h, 128, 128);
736 Num128++;
738 if(w < width) {
739 ListPartial = Enlist(
740 ListPartial, x + w, y + h, width - w, 128);
741 NumPartial++;
744 if(h < height) {
745 int d = height - h;
746 for(w = 0; w <= (width - 128); w += 128) {
747 ListPartial = Enlist(ListPartial, x + w, y + h, 128, d);
748 NumPartial++;
750 if(w < width) {
751 ListPartial = Enlist(ListPartial, x + w, y + h, width - w, d);
752 NumPartial++;
755 pBox++;
760 by this point we've carved the space into as many 512x512, 256x256
761 and 128x128 blocks as we could fit. We will then break larger
762 blocks into smaller ones if we need to. The rules are as follows:
764 512x512 -
765 1) Don't take up more than half the memory.
766 2) Don't bother if you can't get at least four.
767 3) Don't make more than MAX_512.
768 4) Don't have any of there are no 256x256s.
770 256x256 -
771 1) Don't take up more than a quarter of the memory enless there
772 aren't any 512x512s. Then we can take up to half.
773 2) Don't bother if you can't get at least four.
774 3) Don't make more than MAX_256.
776 128x128 -
777 1) Don't make more than MAX_128.
779 We don't bother with the partial blocks unless we can use them
780 for 8x8 pattern fills or we are short on larger blocks.
784 ntotal = Num128 + (Num256<<2) + (Num512<<4);
786 Target512 = ntotal >> 5;
787 if(Target512 < 4) Target512 = 0;
788 if(!Target512) Target256 = ntotal >> 3;
789 else Target256 = ntotal >> 4;
790 if(Target256 < 4) Target256 = 0;
792 if(Num512 && Num256 < 4) {
793 while(Num512 && Num256 < Target256) {
794 SubdivideList(&List512, &List256);
795 Num256 += 4; Num512--;
799 if(!Num512) { /* no room */
800 } else if((Num512 < 4) || (!Target512)) {
801 while(Num512) {
802 SubdivideList(&List512, &List256);
803 Num256 += 4; Num512--;
805 } else if((Num512 > MAX_512) || (Num512 > Target512)){
806 while(Num512 > MAX_512) {
807 SubdivideList(&List512, &List256);
808 Num256 += 4; Num512--;
810 while(Num512 > Target512) {
811 if(Num256 < MAX_256) {
812 SubdivideList(&List512, &List256);
813 Num256 += 4; Num512--;
814 } else break;
818 if(!Num256) { /* no room */
819 } else if((Num256 < 4) || (!Target256)) {
820 while(Num256) {
821 SubdivideList(&List256, &List128);
822 Num128 += 4; Num256--;
824 } else if((Num256 > MAX_256) || (Num256 > Target256)) {
825 while(Num256 > MAX_256) {
826 SubdivideList(&List256, &List128);
827 Num128 += 4; Num256--;
829 while(Num256 > Target256) {
830 if(Num128 < MAX_128) {
831 SubdivideList(&List256, &List128);
832 Num128 += 4; Num256--;
833 } else break;
837 if(Num128 && ((Num128 < 4) || (Num128 > MAX_128))) {
838 CacheLinkPtr next;
839 int max = (Num128 > MAX_128) ? MAX_128 : 0;
842 * Note: next is set in this way to work around a code generation
843 * bug in gcc 2.7.2.3.
845 next = List128->next;
846 while(Num128 > max) {
847 List128->next = ListPartial;
848 ListPartial = List128;
849 if((List128 = next))
850 next = List128->next;
851 NumPartial++; Num128--;
855 MaxPartialHeight = MaxPartialWidth = 0;
857 /* at this point we have as many 512x512 and 256x256 slots as we
858 want but may have an excess of 128x128 slots. We still need
859 to find out if we need 8x8 slots. We take these from the
860 partials if we have them. Otherwise, we break some 128x128's */
862 if(!(infoRec->PixmapCacheFlags & (CACHE_MONO_8x8 | CACHE_COLOR_8x8))) {
863 if(NumPartial) {
864 if(Num128) { /* don't bother with partials */
865 FreeList(ListPartial);
866 NumPartial = 0; ListPartial = NULL;
867 } else {
868 /* We have no big slots. Weed out the unusable partials */
869 ListPartial = ThinOutPartials(ListPartial, &NumPartial,
870 &MaxPartialWidth, &MaxPartialHeight);
873 } else {
874 int MonosPerColor = 1;
875 int ColorH = infoRec->CacheHeightColor8x8Pattern;
876 int ColorW = infoRec->CacheWidthColor8x8Pattern;
877 int MonoH = infoRec->CacheHeightMono8x8Pattern;
878 int MonoW = infoRec->CacheWidthMono8x8Pattern;
879 Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8);
880 Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8);
882 if(DoColor) infoRec->CanDoColor8x8 = FALSE;
883 if(DoMono) infoRec->CanDoMono8x8 = FALSE;
885 if(DoColor && DoMono) {
886 /* we assume color patterns take more space than color ones */
887 if(MonoH > ColorH) ColorH = MonoH;
888 if(MonoW > ColorW) ColorW = MonoW;
889 MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW);
892 if(Num128) {
893 if(NumPartial) { /* use all for 8x8 slots */
894 ConvertAllPartialsTo8x8(&NumMono, &NumColor,
895 ListPartial, &ListMono, &ListColor, infoRec);
896 NumPartial = 0; ListPartial = NULL;
899 /* Get some 8x8 slots from the 128 slots */
900 while((Num128 > 4) &&
901 ((NumMono < MAX_MONO) && (NumColor < MAX_COLOR))) {
902 CacheLinkPtr tmp = NULL;
904 tmp = Enlist(tmp, List128->x, List128->y,
905 List128->w, List128->h);
906 List128 = Delist(List128);
907 Num128--;
909 ConvertAllPartialsTo8x8(&NumMono, &NumColor,
910 tmp, &ListMono, &ListColor, infoRec);
912 } else if(NumPartial) {
913 /* We have share partials between 8x8 slots and tiles. */
914 ListPartial = ConvertSomePartialsTo8x8(&NumMono, &NumColor,
915 &NumPartial, ListPartial, &ListMono, &ListColor,
916 &MaxPartialWidth, &MaxPartialHeight, infoRec);
920 if(DoMono && DoColor) {
921 if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) {
922 int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0;
924 while(NumColor > max) {
925 ConvertColorToMono(&ListColor, ColorW, ColorH,
926 &ListMono, MonoW, MonoH);
927 NumColor--; NumMono += MonosPerColor;
931 /* favor Mono slots over Color ones */
932 while((NumColor > 4) && (NumMono < MAX_MONO)) {
933 ConvertColorToMono(&ListColor, ColorW, ColorH,
934 &ListMono, MonoW, MonoH);
935 NumColor--; NumMono += MonosPerColor;
939 if(NumMono && ((NumMono > MAX_MONO) || (NumMono < 4))) {
940 int max = (NumMono > MAX_MONO) ? MAX_MONO : 0;
942 while(NumMono > max) {
943 ListMono = Delist(ListMono);
944 NumMono--;
947 if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) {
948 int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0;
950 while(NumColor > max) {
951 ListColor = Delist(ListColor);
952 NumColor--;
958 pCachePriv = xcalloc(1,sizeof(XAAPixmapCachePrivate));
959 if(!pCachePriv) {
960 if(Num512) FreeList(List512);
961 if(Num256) FreeList(List256);
962 if(Num128) FreeList(List128);
963 if(NumPartial) FreeList(ListPartial);
964 if(NumColor) FreeList(ListColor);
965 if(NumMono) FreeList(ListMono);
966 return;
969 infoRec->PixmapCachePrivate = (char*)pCachePriv;
971 if(Num512) {
972 pCachePriv->Info512 = xcalloc(Num512,sizeof(XAACacheInfoRec));
973 if(!pCachePriv->Info512) Num512 = 0;
974 if(Num512) TransferList(List512, pCachePriv->Info512, Num512);
975 FreeList(List512);
976 pCachePriv->Num512x512 = Num512;
978 if(Num256) {
979 pCachePriv->Info256 = xcalloc(Num256, sizeof(XAACacheInfoRec));
980 if(!pCachePriv->Info256) Num256 = 0;
981 if(Num256) TransferList(List256, pCachePriv->Info256, Num256);
982 FreeList(List256);
983 pCachePriv->Num256x256 = Num256;
985 if(Num128) {
986 pCachePriv->Info128 = xcalloc(Num128, sizeof(XAACacheInfoRec));
987 if(!pCachePriv->Info128) Num128 = 0;
988 if(Num128) TransferList(List128, pCachePriv->Info128, Num128);
989 FreeList(List128);
990 pCachePriv->Num128x128 = Num128;
993 if(NumPartial) {
994 pCachePriv->InfoPartial = xcalloc(NumPartial, sizeof(XAACacheInfoRec));
995 if(!pCachePriv->InfoPartial) NumPartial = 0;
996 if(NumPartial)
997 TransferList(ListPartial, pCachePriv->InfoPartial, NumPartial);
998 FreeList(ListPartial);
999 pCachePriv->NumPartial = NumPartial;
1002 if(NumColor) {
1003 pCachePriv->InfoColor = xcalloc(NumColor, sizeof(XAACacheInfoRec));
1004 if(!pCachePriv->InfoColor) NumColor = 0;
1005 if(NumColor) TransferList(ListColor, pCachePriv->InfoColor, NumColor);
1006 FreeList(ListColor);
1007 pCachePriv->NumColor = NumColor;
1010 if(NumMono) {
1011 pCachePriv->InfoMono = xcalloc(NumMono, sizeof(XAACacheInfoRec));
1012 if(!pCachePriv->InfoMono) NumMono = 0;
1013 if(NumMono) TransferList(ListMono, pCachePriv->InfoMono, NumMono);
1014 FreeList(ListMono);
1015 pCachePriv->NumMono = NumMono;
1019 if(NumPartial) {
1020 infoRec->MaxCacheableTileWidth = MaxPartialWidth;
1021 infoRec->MaxCacheableTileHeight = MaxPartialHeight;
1023 if(Num128)
1024 infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 128;
1025 if(Num256)
1026 infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 256;
1027 if(Num512)
1028 infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 512;
1031 infoRec->MaxCacheableStippleHeight = infoRec->MaxCacheableTileHeight;
1032 infoRec->MaxCacheableStippleWidth =
1033 infoRec->MaxCacheableTileWidth * pScrn->bitsPerPixel;
1034 if(infoRec->ScreenToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP)
1035 infoRec->MaxCacheableStippleWidth /= 3;
1037 if(NumMono) {
1038 if(!(infoRec->Mono8x8PatternFillFlags &
1039 (HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
1040 HARDWARE_PATTERN_PROGRAMMED_BITS))) {
1041 int numPerLine =
1042 infoRec->CacheWidthMono8x8Pattern/infoRec->MonoPatternPitch;
1044 for(i = 0; i < 64; i++) {
1045 pCachePriv->MonoOffsets[i].y = i/numPerLine;
1046 pCachePriv->MonoOffsets[i].x = (i % numPerLine) *
1047 infoRec->MonoPatternPitch;
1050 infoRec->CanDoMono8x8 = TRUE;
1052 if(NumColor) {
1053 if(!(infoRec->Color8x8PatternFillFlags &
1054 HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) {
1056 for(i = 0; i < 64; i++) {
1057 pCachePriv->ColorOffsets[i].y = i & 0x07;
1058 pCachePriv->ColorOffsets[i].x = i & ~0x07;
1061 infoRec->CanDoColor8x8 = TRUE;
1064 if(!CACHEINIT(pScrn)) {
1065 xf86ErrorF("\tSetting up tile and stipple cache:\n");
1066 if(NumPartial)
1067 xf86ErrorF("\t\t%i %ix%i slots\n",
1068 NumPartial, MaxPartialWidth, MaxPartialHeight);
1069 if(Num128) xf86ErrorF("\t\t%i 128x128 slots\n", Num128);
1070 if(Num256) xf86ErrorF("\t\t%i 256x256 slots\n", Num256);
1071 if(Num512) xf86ErrorF("\t\t%i 512x512 slots\n", Num512);
1072 if(NumColor) xf86ErrorF("\t\t%i 8x8 color pattern slots\n", NumColor);
1073 if(NumMono) xf86ErrorF("\t\t%i 8x8 color expansion slots\n", NumMono);
1076 if(!(NumPartial | Num128 | Num256 | Num512 | NumColor | NumMono)) {
1077 if(!CACHEINIT(pScrn))
1078 xf86ErrorF("\t\tNot enough video memory for pixmap cache\n");
1079 } else infoRec->UsingPixmapCache = TRUE;
1081 CACHEINIT(pScrn) = 1;
1084 #if X_BYTE_ORDER == X_BIG_ENDIAN
1085 static CARD32 StippleMasks[4] = {
1086 0x80808080,
1087 0xC0C0C0C0,
1088 0x00000000,
1089 0xF0F0F0F0
1091 #else
1092 static CARD32 StippleMasks[4] = {
1093 0x01010101,
1094 0x03030303,
1095 0x00000000,
1096 0x0F0F0F0F
1098 #endif
1100 Bool
1101 XAACheckStippleReducibility(PixmapPtr pPixmap)
1103 XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap);
1104 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable);
1105 CARD32 *IntPtr = (CARD32*)pPixmap->devPrivate.ptr;
1106 int w = pPixmap->drawable.width;
1107 int h = pPixmap->drawable.height;
1108 int i;
1109 CARD32 bits[8];
1110 CARD32 mask = SHIFT_R(0xFFFFFFFF,24);
1112 pPriv->flags |= REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR;
1113 pPriv->flags &= ~REDUCIBLE_TO_8x8;
1115 if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1)))
1116 return FALSE;
1118 i = (h > 8) ? 8 : h;
1120 switch(w) {
1121 case 32:
1122 while(i--) {
1123 bits[i] = IntPtr[i] & mask;
1124 if( (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask, 8)), 8)) ||
1125 (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,16)),16)) ||
1126 (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,24)),24)))
1127 return FALSE;
1129 break;
1130 case 16:
1131 while(i--) {
1132 bits[i] = IntPtr[i] & mask;
1133 if(bits[i] != ((IntPtr[i] & SHIFT_R(SHIFT_L(mask,8),8))))
1134 return FALSE;
1136 break;
1137 default:
1138 while(i--)
1139 bits[i] = IntPtr[i] & mask;
1140 break;
1143 switch(h) {
1144 case 32:
1145 if( (IntPtr[8] != IntPtr[16]) || (IntPtr[9] != IntPtr[17]) ||
1146 (IntPtr[10] != IntPtr[18]) || (IntPtr[11] != IntPtr[19]) ||
1147 (IntPtr[12] != IntPtr[20]) || (IntPtr[13] != IntPtr[21]) ||
1148 (IntPtr[14] != IntPtr[22]) || (IntPtr[15] != IntPtr[23]) ||
1149 (IntPtr[16] != IntPtr[24]) || (IntPtr[17] != IntPtr[25]) ||
1150 (IntPtr[18] != IntPtr[26]) || (IntPtr[19] != IntPtr[27]) ||
1151 (IntPtr[20] != IntPtr[28]) || (IntPtr[21] != IntPtr[29]) ||
1152 (IntPtr[22] != IntPtr[30]) || (IntPtr[23] != IntPtr[31]))
1153 return FALSE;
1154 /* fall through */
1155 case 16:
1156 if( (IntPtr[0] != IntPtr[8]) || (IntPtr[1] != IntPtr[9]) ||
1157 (IntPtr[2] != IntPtr[10]) || (IntPtr[3] != IntPtr[11]) ||
1158 (IntPtr[4] != IntPtr[12]) || (IntPtr[5] != IntPtr[13]) ||
1159 (IntPtr[6] != IntPtr[14]) || (IntPtr[7] != IntPtr[15]))
1160 return FALSE;
1161 case 8: break;
1162 case 1: bits[1] = bits[0];
1163 case 2: bits[2] = bits[0]; bits[3] = bits[1];
1164 case 4: bits[4] = bits[0]; bits[5] = bits[1];
1165 bits[6] = bits[2]; bits[7] = bits[3];
1166 break;
1169 pPriv->flags |= REDUCIBLE_TO_8x8;
1171 pPriv->pattern0 = bits[0] | SHIFT_L(bits[1],8) | SHIFT_L(bits[2],16) | SHIFT_L(bits[3],24);
1172 pPriv->pattern1 = bits[4] | SHIFT_L(bits[5],8) | SHIFT_L(bits[6],16) | SHIFT_L(bits[7],24);
1174 if(w < 8) {
1175 pPriv->pattern0 &= StippleMasks[w - 1];
1176 pPriv->pattern1 &= StippleMasks[w - 1];
1178 switch(w) {
1179 case 1: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,1);
1180 pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,1);
1181 case 2: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,2);
1182 pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,2);
1183 case 4: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,4);
1184 pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,4);
1188 if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) {
1189 pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0);
1190 pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1);
1194 return TRUE;
1198 Bool
1199 XAACheckTileReducibility(PixmapPtr pPixmap, Bool checkMono)
1201 XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap);
1202 CARD32 *IntPtr;
1203 int w = pPixmap->drawable.width;
1204 int h = pPixmap->drawable.height;
1205 int pitch = pPixmap->devKind >> 2;
1206 int dwords, i, j;
1208 pPriv->flags |= REDUCIBILITY_CHECKED;
1209 pPriv->flags &= ~(REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR);
1211 if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1)))
1212 return FALSE;
1214 dwords = ((w * pPixmap->drawable.bitsPerPixel) + 31) >> 5;
1215 i = (h > 8) ? 8 : h;
1218 if(w > 8) {
1219 IntPtr = (CARD32*)pPixmap->devPrivate.ptr;
1220 switch(pPixmap->drawable.bitsPerPixel) {
1221 case 8:
1222 while(i--) {
1223 for(j = 2; j < dwords; j++)
1224 if(IntPtr[j] != IntPtr[j & 0x01])
1225 return FALSE;
1226 IntPtr += pitch;
1228 break;
1229 case 16:
1230 while(i--) {
1231 for(j = 4; j < dwords; j++)
1232 if(IntPtr[j] != IntPtr[j & 0x03])
1233 return FALSE;
1234 IntPtr += pitch;
1236 break;
1237 case 24:
1238 while(i--) {
1239 for(j = 6; j < dwords; j++)
1240 if(IntPtr[j] != IntPtr[j % 6])
1241 return FALSE;
1242 IntPtr += pitch;
1244 break;
1245 case 32:
1246 while(i--) {
1247 for(j = 8; j < dwords; j++)
1248 if(IntPtr[j] != IntPtr[j & 0x07])
1249 return FALSE;
1250 IntPtr += pitch;
1252 break;
1253 default: return FALSE;
1259 if(h == 32) {
1260 CARD32 *IntPtr2, *IntPtr3, *IntPtr4;
1261 i = 8;
1262 IntPtr = (CARD32*)pPixmap->devPrivate.ptr;
1263 IntPtr2 = IntPtr + (pitch << 3);
1264 IntPtr3 = IntPtr2 + (pitch << 3);
1265 IntPtr4 = IntPtr3 + (pitch << 3);
1266 while(i--) {
1267 for(j = 0; j < dwords; j++)
1268 if((IntPtr[j] != IntPtr2[j]) || (IntPtr[j] != IntPtr3[j]) ||
1269 (IntPtr[j] != IntPtr4[j]))
1270 return FALSE;
1271 IntPtr += pitch;
1272 IntPtr2 += pitch;
1273 IntPtr3 += pitch;
1274 IntPtr4 += pitch;
1276 } else if (h == 16) {
1277 CARD32 *IntPtr2;
1278 i = 8;
1279 IntPtr = (CARD32*)pPixmap->devPrivate.ptr;
1280 IntPtr2 = IntPtr + (pitch << 3);
1281 while(i--) {
1282 for(j = 0; j < dwords; j++)
1283 if(IntPtr[j] != IntPtr2[j])
1284 return FALSE;
1285 IntPtr += pitch;
1286 IntPtr2 += pitch;
1290 pPriv->flags |= REDUCIBLE_TO_8x8;
1292 if(checkMono) {
1293 XAAInfoRecPtr infoRec =
1294 GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable);
1295 unsigned char bits[8];
1296 int fg, bg = -1, x, y;
1298 i = (h > 8) ? 8 : h;
1299 j = (w > 8) ? 8 : w;
1301 if(pPixmap->drawable.bitsPerPixel == 8) {
1302 unsigned char *srcp = pPixmap->devPrivate.ptr;
1303 fg = srcp[0];
1304 pitch = pPixmap->devKind;
1305 for(y = 0; y < i; y++) {
1306 bits[y] = 0;
1307 for(x = 0; x < j; x++) {
1308 if(srcp[x] != fg) {
1309 if(bg == -1) bg = srcp[x];
1310 else if(bg != srcp[x]) return TRUE;
1311 } else bits[y] |= 1 << x;
1313 srcp += pitch;
1315 } else if(pPixmap->drawable.bitsPerPixel == 16) {
1316 unsigned short *srcp = (unsigned short*)pPixmap->devPrivate.ptr;
1317 fg = srcp[0];
1318 pitch = pPixmap->devKind >> 1;
1319 for(y = 0; y < i; y++) {
1320 bits[y] = 0;
1321 for(x = 0; x < j; x++) {
1322 if(srcp[x] != fg) {
1323 if(bg == -1) bg = srcp[x];
1324 else if(bg != srcp[x]) return TRUE;
1325 } else bits[y] |= 1 << x;
1327 srcp += pitch;
1329 } else if(pPixmap->drawable.bitsPerPixel == 24) {
1330 CARD32 val;
1331 unsigned char *srcp = pPixmap->devPrivate.ptr;
1332 fg = *((CARD32*)srcp) & 0x00FFFFFF;
1333 pitch = pPixmap->devKind;
1334 j *= 3;
1335 for(y = 0; y < i; y++) {
1336 bits[y] = 0;
1337 for(x = 0; x < j; x+=3) {
1338 val = *((CARD32*)(srcp+x)) & 0x00FFFFFF;
1339 if(val != fg) {
1340 if(bg == -1) bg = val;
1341 else if(bg != val)
1342 return TRUE;
1343 } else bits[y] |= 1 << (x/3);
1345 srcp += pitch;
1347 } else if(pPixmap->drawable.bitsPerPixel == 32) {
1348 IntPtr = (CARD32*)pPixmap->devPrivate.ptr;
1349 fg = IntPtr[0];
1350 for(y = 0; y < i; y++) {
1351 bits[y] = 0;
1352 for(x = 0; x < j; x++) {
1353 if(IntPtr[x] != fg) {
1354 if(bg == -1) bg = IntPtr[x];
1355 else if(bg != IntPtr[x]) return TRUE;
1356 } else bits[y] |= 1 << x;
1358 IntPtr += pitch;
1360 } else return TRUE;
1362 pPriv->fg = fg;
1363 if(bg == -1) pPriv->bg = fg;
1364 else pPriv->bg = bg;
1366 if(h < 8) {
1367 switch(h) {
1368 case 1: bits[1] = bits[0];
1369 case 2: bits[2] = bits[0]; bits[3] = bits[1];
1370 case 4: bits[4] = bits[0]; bits[5] = bits[1];
1371 bits[6] = bits[2]; bits[7] = bits[3];
1372 break;
1376 pPriv->pattern0 =
1377 bits[0] | (bits[1]<<8) | (bits[2]<<16) | (bits[3]<<24);
1378 pPriv->pattern1 =
1379 bits[4] | (bits[5]<<8) | (bits[6]<<16) | (bits[7]<<24);
1381 if(w < 8) {
1382 switch(w) {
1383 case 1: pPriv->pattern0 |= (pPriv->pattern0 << 1);
1384 pPriv->pattern1 |= (pPriv->pattern1 << 1);
1385 case 2: pPriv->pattern0 |= (pPriv->pattern0 << 2);
1386 pPriv->pattern1 |= (pPriv->pattern1 << 2);
1387 case 4: pPriv->pattern0 |= (pPriv->pattern0 << 4);
1388 pPriv->pattern1 |= (pPriv->pattern1 << 4);
1391 pPriv->flags |= REDUCIBLE_TO_2_COLOR;
1393 if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) {
1394 pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0);
1395 pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1);
1400 return TRUE;
1404 void XAATileCache(
1405 ScrnInfoPtr pScrn,
1406 XAACacheInfoPtr pCache,
1407 int w, int h
1409 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
1411 (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, ~0, -1);
1413 while((w << 1) <= pCache->w) {
1414 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y,
1415 pCache->x + w, pCache->y, w, h);
1416 w <<= 1;
1418 if(w != pCache->w) {
1419 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y,
1420 pCache->x + w, pCache->y, pCache->w - w, h);
1421 w = pCache->w;
1424 while((h << 1) <= pCache->h) {
1425 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y,
1426 pCache->x, pCache->y + h, w, h);
1427 h <<= 1;
1429 if(h != pCache->h) {
1430 (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y,
1431 pCache->x, pCache->y + h, w, pCache->h - h);
1433 SET_SYNC_FLAG(infoRec);
1436 XAACacheInfoPtr
1437 XAACacheTile(ScrnInfoPtr pScrn, PixmapPtr pPix)
1439 int w = pPix->drawable.width;
1440 int h = pPix->drawable.height;
1441 int size = max(w, h);
1442 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
1443 XAAPixmapCachePrivatePtr pCachePriv =
1444 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate;
1445 XAACacheInfoPtr pCache, cacheRoot = NULL;
1446 int i, max = 0;
1447 int *current;
1449 if(size <= 128) {
1450 if(pCachePriv->Info128) {
1451 cacheRoot = pCachePriv->Info128;
1452 max = pCachePriv->Num128x128;
1453 current = &pCachePriv->Current128;
1454 } else {
1455 cacheRoot = pCachePriv->InfoPartial;
1456 max = pCachePriv->NumPartial;
1457 current = &pCachePriv->CurrentPartial;
1459 } else if(size <= 256) {
1460 cacheRoot = pCachePriv->Info256;
1461 max = pCachePriv->Num256x256;
1462 current = &pCachePriv->Current256;
1463 } else if(size <= 512) {
1464 cacheRoot = pCachePriv->Info512;
1465 max = pCachePriv->Num512x512;
1466 current = &pCachePriv->Current512;
1467 } else { /* something's wrong */
1468 ErrorF("Something's wrong in XAACacheTile()\n");
1469 return pCachePriv->Info128;
1472 pCache = cacheRoot;
1474 /* lets look for it */
1475 for(i = 0; i < max; i++, pCache++) {
1476 if(pCache->serialNumber == pPix->drawable.serialNumber) {
1477 pCache->trans_color = -1;
1478 return pCache;
1482 pCache = &cacheRoot[(*current)++];
1483 if(*current >= max) *current = 0;
1485 pCache->serialNumber = pPix->drawable.serialNumber;
1486 pCache->trans_color = pCache->bg = pCache->fg = -1;
1487 pCache->orig_w = w; pCache->orig_h = h;
1488 (*infoRec->WritePixmapToCache)(
1489 pScrn, pCache->x, pCache->y, w, h, pPix->devPrivate.ptr,
1490 pPix->devKind, pPix->drawable.bitsPerPixel, pPix->drawable.depth);
1491 if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) &&
1492 ((w != pCache->w) || (h != pCache->h)))
1493 XAATileCache(pScrn, pCache, w, h);
1495 return pCache;
1498 XAACacheInfoPtr
1499 XAACacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix)
1501 int w = pPix->drawable.width;
1502 int h = pPix->drawable.height;
1503 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
1504 XAAPixmapCachePrivatePtr pCachePriv =
1505 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate;
1506 XAACacheInfoPtr pCache, cacheRoot = NULL;
1507 int i, max = 0, funcNo, pad, dwords, bpp = pScrn->bitsPerPixel;
1508 int *current;
1509 StippleScanlineProcPtr StippleFunc;
1510 unsigned char *data, *srcPtr, *dstPtr;
1512 if((h <= 128) && (w <= 128 * bpp)) {
1513 if(pCachePriv->Info128) {
1514 cacheRoot = pCachePriv->Info128;
1515 max = pCachePriv->Num128x128;
1516 current = &pCachePriv->Current128;
1517 } else {
1518 cacheRoot = pCachePriv->InfoPartial;
1519 max = pCachePriv->NumPartial;
1520 current = &pCachePriv->CurrentPartial;
1522 } else if((h <= 256) && (w <= 256 * bpp)){
1523 cacheRoot = pCachePriv->Info256;
1524 max = pCachePriv->Num256x256;
1525 current = &pCachePriv->Current256;
1526 } else if((h <= 512) && (w <= 526 * bpp)){
1527 cacheRoot = pCachePriv->Info512;
1528 max = pCachePriv->Num512x512;
1529 current = &pCachePriv->Current512;
1530 } else { /* something's wrong */
1531 ErrorF("Something's wrong in XAACacheMonoStipple()\n");
1532 return pCachePriv->Info128;
1535 pCache = cacheRoot;
1537 /* lets look for it */
1538 for(i = 0; i < max; i++, pCache++) {
1539 if((pCache->serialNumber == pPix->drawable.serialNumber) &&
1540 (pCache->fg == -1) && (pCache->bg == -1)) {
1541 pCache->trans_color = -1;
1542 return pCache;
1546 pCache = &cacheRoot[(*current)++];
1547 if(*current >= max) *current = 0;
1549 pCache->serialNumber = pPix->drawable.serialNumber;
1550 pCache->trans_color = pCache->bg = pCache->fg = -1;
1551 pCache->orig_w = w; pCache->orig_h = h;
1553 if(w <= 32) {
1554 if(w & (w - 1)) funcNo = 1;
1555 else funcNo = 0;
1556 } else funcNo = 2;
1558 pad = BitmapBytePad(pCache->w * bpp);
1559 dwords = pad >> 2;
1560 dstPtr = data = (unsigned char*)ALLOCATE_LOCAL(pad * pCache->h);
1561 srcPtr = (unsigned char*)pPix->devPrivate.ptr;
1563 if(infoRec->ScreenToScreenColorExpandFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST)
1564 StippleFunc = XAAStippleScanlineFuncMSBFirst[funcNo];
1565 else
1566 StippleFunc = XAAStippleScanlineFuncLSBFirst[funcNo];
1568 /* don't bother generating more than we'll ever use */
1569 max = ((pScrn->displayWidth + w - 1) + 31) >> 5;
1570 if(dwords > max)
1571 dwords = max;
1573 for(i = 0; i < h; i++) {
1574 (*StippleFunc)((CARD32*)dstPtr, (CARD32*)srcPtr, 0, w, dwords);
1575 srcPtr += pPix->devKind;
1576 dstPtr += pad;
1579 while((h<<1) <= pCache->h) {
1580 memcpy(data + (pad * h), data, pad * h);
1581 h <<= 1;
1584 if(h < pCache->h)
1585 memcpy(data + (pad * h), data, pad * (pCache->h - h));
1587 (*infoRec->WritePixmapToCache)(
1588 pScrn, pCache->x, pCache->y, pCache->w, pCache->h, data,
1589 pad, bpp, pScrn->depth);
1591 DEALLOCATE_LOCAL(data);
1593 return pCache;
1596 XAACacheInfoPtr
1597 XAACachePlanarMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix)
1599 int w = pPix->drawable.width;
1600 int h = pPix->drawable.height;
1601 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
1602 XAAPixmapCachePrivatePtr pCachePriv =
1603 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate;
1604 XAACacheInfoPtr pCache, cacheRoot = NULL;
1605 int i, max = 0;
1606 int *current;
1608 if((h <= 128) && (w <= 128)) {
1609 if(pCachePriv->Info128) {
1610 cacheRoot = pCachePriv->Info128;
1611 max = pCachePriv->Num128x128;
1612 current = &pCachePriv->Current128;
1613 } else {
1614 cacheRoot = pCachePriv->InfoPartial;
1615 max = pCachePriv->NumPartial;
1616 current = &pCachePriv->CurrentPartial;
1618 } else if((h <= 256) && (w <= 256)){
1619 cacheRoot = pCachePriv->Info256;
1620 max = pCachePriv->Num256x256;
1621 current = &pCachePriv->Current256;
1622 } else if((h <= 512) && (w <= 526)){
1623 cacheRoot = pCachePriv->Info512;
1624 max = pCachePriv->Num512x512;
1625 current = &pCachePriv->Current512;
1626 } else { /* something's wrong */
1627 ErrorF("Something's wrong in XAACachePlanarMonoStipple()\n");
1628 return pCachePriv->Info128;
1631 pCache = cacheRoot;
1633 /* lets look for it */
1634 for(i = 0; i < max; i++, pCache++) {
1635 if((pCache->serialNumber == pPix->drawable.serialNumber) &&
1636 (pCache->fg == -1) && (pCache->bg == -1)) {
1637 pCache->trans_color = -1;
1638 return pCache;
1642 pCache = &cacheRoot[(*current)++];
1643 if(*current >= max) *current = 0;
1645 pCache->serialNumber = pPix->drawable.serialNumber;
1646 pCache->trans_color = pCache->bg = pCache->fg = -1;
1647 pCache->orig_w = w; pCache->orig_h = h;
1649 /* Plane 0 holds the stipple. Plane 1 holds the inverted stipple */
1650 (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y,
1651 pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr,
1652 pPix->devKind, 1, 2);
1653 if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_MONO_DATA) &&
1654 ((w != pCache->w) || (h != pCache->h)))
1655 XAATileCache(pScrn, pCache, w, h);
1657 return pCache;
1660 XAACachePlanarMonoStippleProc
1661 XAAGetCachePlanarMonoStipple(void) { return XAACachePlanarMonoStipple; }
1663 XAACacheInfoPtr
1664 XAACacheStipple(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg)
1666 int w = pPix->drawable.width;
1667 int h = pPix->drawable.height;
1668 int size = max(w, h);
1669 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
1670 XAAPixmapCachePrivatePtr pCachePriv =
1671 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate;
1672 XAACacheInfoPtr pCache, cacheRoot = NULL;
1673 int i, max = 0;
1674 int *current;
1676 if(size <= 128) {
1677 if(pCachePriv->Info128) {
1678 cacheRoot = pCachePriv->Info128;
1679 max = pCachePriv->Num128x128;
1680 current = &pCachePriv->Current128;
1681 } else {
1682 cacheRoot = pCachePriv->InfoPartial;
1683 max = pCachePriv->NumPartial;
1684 current = &pCachePriv->CurrentPartial;
1686 } else if(size <= 256) {
1687 cacheRoot = pCachePriv->Info256;
1688 max = pCachePriv->Num256x256;
1689 current = &pCachePriv->Current256;
1690 } else if(size <= 512) {
1691 cacheRoot = pCachePriv->Info512;
1692 max = pCachePriv->Num512x512;
1693 current = &pCachePriv->Current512;
1694 } else { /* something's wrong */
1695 ErrorF("Something's wrong in XAACacheStipple()\n");
1696 return pCachePriv->Info128;
1699 pCache = cacheRoot;
1700 /* lets look for it */
1701 if(bg == -1)
1702 for(i = 0; i < max; i++, pCache++) {
1703 if((pCache->serialNumber == pPix->drawable.serialNumber) &&
1704 (fg == pCache->fg) && (pCache->fg != pCache->bg)) {
1705 pCache->trans_color = pCache->bg;
1706 return pCache;
1709 else
1710 for(i = 0; i < max; i++, pCache++) {
1711 if((pCache->serialNumber == pPix->drawable.serialNumber) &&
1712 (fg == pCache->fg) && (bg == pCache->bg)) {
1713 pCache->trans_color = -1;
1714 return pCache;
1718 pCache = &cacheRoot[(*current)++];
1719 if(*current >= max) *current = 0;
1721 pCache->serialNumber = pPix->drawable.serialNumber;
1722 pCache->fg = fg;
1723 if(bg == -1)
1724 pCache->trans_color = bg = fg ^ 1;
1725 else
1726 pCache->trans_color = -1;
1727 pCache->bg = bg;
1729 pCache->orig_w = w; pCache->orig_h = h;
1730 (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y,
1731 pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr,
1732 pPix->devKind, fg, bg);
1733 if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) &&
1734 ((w != pCache->w) || (h != pCache->h)))
1735 XAATileCache(pScrn, pCache, w, h);
1737 return pCache;
1742 XAACacheInfoPtr
1743 XAACacheMono8x8Pattern(ScrnInfoPtr pScrn, int pat0, int pat1)
1745 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
1746 XAAPixmapCachePrivatePtr pCachePriv =
1747 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate;
1748 XAACacheInfoPtr pCache = pCachePriv->InfoMono;
1749 int i;
1751 for(i = 0; i < pCachePriv->NumMono; i++, pCache++) {
1752 if(pCache->serialNumber &&
1753 (pCache->pat0 == pat0) && (pCache->pat1 == pat1))
1754 return pCache;
1757 /* OK, let's cache it */
1758 pCache = &pCachePriv->InfoMono[pCachePriv->CurrentMono++];
1759 if(pCachePriv->CurrentMono >= pCachePriv->NumMono)
1760 pCachePriv->CurrentMono = 0;
1762 pCache->serialNumber = 1; /* we don't care since we do lookups by pattern */
1763 pCache->pat0 = pat0;
1764 pCache->pat1 = pat1;
1766 (*infoRec->WriteMono8x8PatternToCache)(pScrn, pCache);
1768 return pCache;
1773 XAACacheInfoPtr
1774 XAACacheColor8x8Pattern(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg)
1776 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
1777 XAAPixmapCachePrivatePtr pCachePriv =
1778 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate;
1779 XAACacheInfoPtr pCache = pCachePriv->InfoColor;
1780 XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix);
1781 int i;
1783 if(!(pixPriv->flags & REDUCIBLE_TO_2_COLOR)) {
1784 for(i = 0; i < pCachePriv->NumColor; i++, pCache++) {
1785 if(pCache->serialNumber == pPix->drawable.serialNumber) {
1786 pCache->trans_color = -1;
1787 return pCache;
1790 pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++];
1791 if(pCachePriv->CurrentColor >= pCachePriv->NumColor)
1792 pCachePriv->CurrentColor = 0;
1794 pCache->serialNumber = pPix->drawable.serialNumber;
1795 pCache->trans_color = pCache->fg = pCache->bg = -1;
1796 } else {
1797 int pat0 = pixPriv->pattern0;
1798 int pat1 = pixPriv->pattern1;
1800 if(fg == -1) { /* it's a tile */
1801 fg = pixPriv->fg; bg = pixPriv->bg;
1804 if(bg == -1) { /* stipple */
1805 for(i = 0; i < pCachePriv->NumColor; i++, pCache++) {
1806 if(pCache->serialNumber &&
1807 (pCache->pat0 == pat0) && (pCache->pat1 == pat1) &&
1808 (pCache->fg == fg) && (pCache->bg != fg)) {
1809 pCache->trans_color = pCache->bg;
1810 return pCache;
1813 } else { /* opaque stipple */
1814 for(i = 0; i < pCachePriv->NumColor; i++, pCache++) {
1815 if(pCache->serialNumber &&
1816 (pCache->pat0 == pat0) && (pCache->pat1 == pat1) &&
1817 (pCache->fg == fg) && (pCache->bg == bg)) {
1818 pCache->trans_color = -1;
1819 return pCache;
1823 pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++];
1824 if(pCachePriv->CurrentColor >= pCachePriv->NumColor)
1825 pCachePriv->CurrentColor = 0;
1827 if(bg == -1)
1828 pCache->trans_color = bg = fg ^ 1;
1829 else
1830 pCache->trans_color = -1;
1832 pCache->pat0 = pat0; pCache->pat1 = pat1;
1833 pCache->fg = fg; pCache->bg = bg;
1834 pCache->serialNumber = 1;
1837 (*infoRec->WriteColor8x8PatternToCache)(pScrn, pPix, pCache);
1839 return pCache;
1843 void
1844 XAAWriteBitmapToCache(
1845 ScrnInfoPtr pScrn,
1846 int x, int y, int w, int h,
1847 unsigned char *src,
1848 int srcwidth,
1849 int fg, int bg
1851 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
1853 (*infoRec->WriteBitmap)(pScrn, x, y, w, h, src, srcwidth,
1854 0, fg, bg, GXcopy, ~0);
1857 void
1858 XAAWriteBitmapToCacheLinear(
1859 ScrnInfoPtr pScrn,
1860 int x, int y, int w, int h,
1861 unsigned char *src,
1862 int srcwidth,
1863 int fg, int bg
1865 ScreenPtr pScreen = pScrn->pScreen;
1866 PixmapPtr pScreenPix, pDstPix;
1867 XID gcvals[2];
1868 GCPtr pGC;
1870 pScreenPix = (*pScreen->GetScreenPixmap)(pScreen);
1872 pDstPix = GetScratchPixmapHeader(pScreen, pScreenPix->drawable.width,
1873 y + h, pScreenPix->drawable.depth,
1874 pScreenPix->drawable.bitsPerPixel,
1875 pScreenPix->devKind,
1876 pScreenPix->devPrivate.ptr);
1878 pGC = GetScratchGC(pScreenPix->drawable.depth, pScreen);
1879 gcvals[0] = fg;
1880 gcvals[1] = bg;
1881 DoChangeGC(pGC, GCForeground | GCBackground, gcvals, 0);
1882 ValidateGC((DrawablePtr)pDstPix, pGC);
1884 /* We've unwrapped already so these ops miss a sync */
1885 SYNC_CHECK(pScrn);
1887 (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, 1, x, y, w, h, 0,
1888 XYBitmap, (pointer)src);
1890 FreeScratchGC(pGC);
1891 FreeScratchPixmapHeader(pDstPix);
1895 void
1896 XAAWritePixmapToCache(
1897 ScrnInfoPtr pScrn,
1898 int x, int y, int w, int h,
1899 unsigned char *src,
1900 int srcwidth,
1901 int bpp, int depth
1903 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
1905 (*infoRec->WritePixmap)(pScrn, x, y, w, h, src, srcwidth,
1906 GXcopy, ~0, -1, bpp, depth);
1911 void
1912 XAAWritePixmapToCacheLinear(
1913 ScrnInfoPtr pScrn,
1914 int x, int y, int w, int h,
1915 unsigned char *src,
1916 int srcwidth,
1917 int bpp, int depth
1919 ScreenPtr pScreen = pScrn->pScreen;
1920 PixmapPtr pScreenPix, pDstPix;
1921 GCPtr pGC;
1923 pScreenPix = (*pScreen->GetScreenPixmap)(pScreen);
1925 pDstPix = GetScratchPixmapHeader(pScreen, x + w, y + h,
1926 depth, bpp, pScreenPix->devKind,
1927 pScreenPix->devPrivate.ptr);
1929 pGC = GetScratchGC(depth, pScreen);
1930 ValidateGC((DrawablePtr)pDstPix, pGC);
1932 /* We've unwrapped already so these ops miss a sync */
1933 SYNC_CHECK(pScrn);
1935 if(bpp == BitsPerPixel(depth))
1936 (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, depth, x, y, w,
1937 h, 0, ZPixmap, (pointer)src);
1938 else {
1939 PixmapPtr pSrcPix;
1941 pSrcPix = GetScratchPixmapHeader(pScreen, w, h, depth, bpp,
1942 srcwidth, (pointer)src);
1944 (*pGC->ops->CopyArea)((DrawablePtr)pSrcPix, (DrawablePtr)pDstPix,
1945 pGC, 0, 0, w, h, x, y);
1947 FreeScratchPixmapHeader(pSrcPix);
1950 FreeScratchGC(pGC);
1951 FreeScratchPixmapHeader(pDstPix);
1955 void
1956 XAAWriteMono8x8PatternToCache(
1957 ScrnInfoPtr pScrn,
1958 XAACacheInfoPtr pCache
1960 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
1961 XAAPixmapCachePrivatePtr pCachePriv =
1962 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate;
1963 unsigned char *data;
1964 int pad, Bpp = (pScrn->bitsPerPixel >> 3);
1966 pCache->offsets = pCachePriv->MonoOffsets;
1968 pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel);
1970 data = (unsigned char*)ALLOCATE_LOCAL(pad * pCache->h);
1971 if(!data) return;
1973 if(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN) {
1974 CARD32* ptr = (CARD32*)data;
1975 ptr[0] = pCache->pat0; ptr[1] = pCache->pat1;
1976 } else {
1977 CARD32 *ptr;
1978 DDXPointPtr pPoint = pCache->offsets;
1979 int patx, paty, i;
1981 for(i = 0; i < 64; i++, pPoint++) {
1982 patx = pCache->pat0; paty = pCache->pat1;
1983 XAARotateMonoPattern(&patx, &paty, i & 0x07, i >> 3,
1984 (infoRec->Mono8x8PatternFillFlags &
1985 BIT_ORDER_IN_BYTE_MSBFIRST));
1986 ptr = (CARD32*)(data + (pad * pPoint->y) + (Bpp * pPoint->x));
1987 ptr[0] = patx; ptr[1] = paty;
1991 (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y,
1992 pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth);
1994 DEALLOCATE_LOCAL(data);
1997 void
1998 XAAWriteColor8x8PatternToCache(
1999 ScrnInfoPtr pScrn,
2000 PixmapPtr pPix,
2001 XAACacheInfoPtr pCache
2003 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
2004 XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix);
2005 XAAPixmapCachePrivatePtr pCachePriv =
2006 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate;
2007 int pad, i, w, h, nw, nh, Bpp;
2008 unsigned char *data, *srcPtr, *dstPtr;
2010 pCache->offsets = pCachePriv->ColorOffsets;
2012 if(pixPriv->flags & REDUCIBLE_TO_2_COLOR) {
2013 CARD32* ptr;
2014 pad = BitmapBytePad(pCache->w);
2015 data = (unsigned char*)ALLOCATE_LOCAL(pad * pCache->h);
2016 if(!data) return;
2018 if(infoRec->Color8x8PatternFillFlags &
2019 HARDWARE_PATTERN_PROGRAMMED_ORIGIN) {
2020 ptr = (CARD32*)data;
2021 ptr[0] = pCache->pat0; ptr[1] = pCache->pat1;
2022 } else {
2023 int patx, paty;
2025 ptr = (CARD32*)data;
2026 ptr[0] = ptr[2] = pCache->pat0; ptr[1] = ptr[3] = pCache->pat1;
2027 for(i = 1; i < 8; i++) {
2028 patx = pCache->pat0; paty = pCache->pat1;
2029 XAARotateMonoPattern(&patx, &paty, i, 0,
2030 (infoRec->Mono8x8PatternFillFlags &
2031 BIT_ORDER_IN_BYTE_MSBFIRST));
2032 ptr = (CARD32*)(data + (pad * i));
2033 ptr[0] = ptr[2] = patx; ptr[1] = ptr[3] = paty;
2037 (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y,
2038 pCache->w, pCache->h, data, pad, pCache->fg, pCache->bg);
2040 DEALLOCATE_LOCAL(data);
2041 return;
2044 Bpp = pScrn->bitsPerPixel >> 3;
2045 h = min(8,pPix->drawable.height);
2046 w = min(8,pPix->drawable.width);
2047 pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel);
2049 data = (unsigned char*)ALLOCATE_LOCAL(pad * pCache->h);
2050 if(!data) return;
2052 /* Write and expand horizontally. */
2053 for (i = h, dstPtr = data, srcPtr = pPix->devPrivate.ptr; i--;
2054 srcPtr += pPix->devKind, dstPtr += pScrn->bitsPerPixel) {
2055 nw = w;
2056 memcpy(dstPtr, srcPtr, w * Bpp);
2057 while (nw != 8) {
2058 memcpy(dstPtr + (nw * Bpp), dstPtr, nw * Bpp);
2059 nw <<= 1;
2062 nh = h;
2063 /* Expand vertically. */
2064 while (nh != 8) {
2065 memcpy(data + (nh*pScrn->bitsPerPixel), data, nh*pScrn->bitsPerPixel);
2066 nh <<= 1;
2069 if(!(infoRec->Color8x8PatternFillFlags &
2070 HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
2071 int j;
2072 unsigned char *ptr = data + (128 * Bpp);
2074 memcpy(data + (64 * Bpp), data, 64 * Bpp);
2075 for(i = 1; i < 8; i++, ptr += (128 * Bpp)) {
2076 for(j = 0; j < 8; j++) {
2077 memcpy(ptr + (j * 8) * Bpp, data + (j * 8 + i) * Bpp,
2078 (8 - i) * Bpp);
2079 memcpy(ptr + (j * 8 + 8 - i) * Bpp, data + j * 8 * Bpp, i*Bpp);
2081 memcpy(ptr + (64 * Bpp), ptr, 64 * Bpp);
2085 (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y,
2086 pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth);
2088 DEALLOCATE_LOCAL(data);
2094 XAAStippledFillChooser(GCPtr pGC)
2096 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
2097 PixmapPtr pPixmap = pGC->stipple;
2098 XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap);
2100 if(!(pPriv->flags & REDUCIBILITY_CHECKED) &&
2101 (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) {
2102 XAACheckStippleReducibility(pPixmap);
2106 if(pPriv->flags & REDUCIBLE_TO_8x8) {
2107 if(infoRec->CanDoMono8x8 &&
2108 !(infoRec->FillMono8x8PatternSpansFlags & NO_TRANSPARENCY) &&
2109 ((pGC->alu == GXcopy) || !(infoRec->FillMono8x8PatternSpansFlags &
2110 TRANSPARENCY_GXCOPY_ONLY)) &&
2111 CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) &&
2112 CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) &&
2113 CHECK_FG(pGC,infoRec->FillMono8x8PatternSpansFlags) &&
2114 CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) {
2116 return DO_MONO_8x8;
2119 if(infoRec->CanDoColor8x8 &&
2120 !(infoRec->FillColor8x8PatternSpansFlags & NO_TRANSPARENCY) &&
2121 ((pGC->alu == GXcopy) || !(infoRec->FillColor8x8PatternSpansFlags &
2122 TRANSPARENCY_GXCOPY_ONLY)) &&
2123 CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) &&
2124 CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) &&
2125 CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) {
2127 return DO_COLOR_8x8;
2131 if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans &&
2132 (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) &&
2133 (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth /
2134 infoRec->CacheColorExpandDensity) &&
2135 !(infoRec->FillCacheExpandSpansFlags & NO_TRANSPARENCY) &&
2136 ((pGC->alu == GXcopy) || !(infoRec->FillCacheExpandSpansFlags &
2137 TRANSPARENCY_GXCOPY_ONLY)) &&
2138 CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) &&
2139 CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) &&
2140 CHECK_FG(pGC,infoRec->FillCacheExpandSpansFlags) &&
2141 CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) {
2143 return DO_CACHE_EXPAND;
2147 if(infoRec->UsingPixmapCache &&
2148 !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) &&
2149 infoRec->FillCacheBltSpans &&
2150 (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) &&
2151 (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) &&
2152 !(infoRec->FillCacheBltSpansFlags & NO_TRANSPARENCY) &&
2153 ((pGC->alu == GXcopy) || !(infoRec->FillCacheBltSpansFlags &
2154 TRANSPARENCY_GXCOPY_ONLY)) &&
2155 CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) &&
2156 CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) &&
2157 CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) {
2159 return DO_CACHE_BLT;
2162 if(infoRec->FillColorExpandSpans &&
2163 !(infoRec->FillColorExpandSpansFlags & NO_TRANSPARENCY) &&
2164 ((pGC->alu == GXcopy) || !(infoRec->FillColorExpandSpansFlags &
2165 TRANSPARENCY_GXCOPY_ONLY)) &&
2166 CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) &&
2167 CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) &&
2168 CHECK_FG(pGC,infoRec->FillColorExpandSpansFlags) &&
2169 CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) {
2171 return DO_COLOR_EXPAND;
2174 return 0;
2179 XAAOpaqueStippledFillChooser(GCPtr pGC)
2181 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
2182 PixmapPtr pPixmap = pGC->stipple;
2183 XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap);
2185 if(XAA_DEPTH_BUG(pGC))
2186 return 0;
2188 if(!(pPriv->flags & REDUCIBILITY_CHECKED) &&
2189 (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) {
2190 XAACheckStippleReducibility(pPixmap);
2193 if(pPriv->flags & REDUCIBLE_TO_8x8) {
2194 if(infoRec->CanDoMono8x8 &&
2195 !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) &&
2196 CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) &&
2197 CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) &&
2198 CHECK_COLORS(pGC,infoRec->FillMono8x8PatternSpansFlags) &&
2199 CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) {
2201 return DO_MONO_8x8;
2204 if(infoRec->CanDoColor8x8 &&
2205 CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) &&
2206 CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) &&
2207 CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) {
2209 return DO_COLOR_8x8;
2213 if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans &&
2214 (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) &&
2215 (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth /
2216 infoRec->CacheColorExpandDensity) &&
2217 !(infoRec->FillCacheExpandSpansFlags & TRANSPARENCY_ONLY) &&
2218 CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) &&
2219 CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) &&
2220 CHECK_COLORS(pGC,infoRec->FillCacheExpandSpansFlags) &&
2221 CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) {
2223 return DO_CACHE_EXPAND;
2226 if(infoRec->UsingPixmapCache &&
2227 !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) &&
2228 infoRec->FillCacheBltSpans &&
2229 (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) &&
2230 (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) &&
2231 CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) &&
2232 CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) &&
2233 CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) {
2235 return DO_CACHE_BLT;
2238 if(infoRec->FillColorExpandSpans &&
2239 !(infoRec->FillColorExpandSpansFlags & TRANSPARENCY_ONLY) &&
2240 CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) &&
2241 CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) &&
2242 CHECK_COLORS(pGC,infoRec->FillColorExpandSpansFlags) &&
2243 CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) {
2245 return DO_COLOR_EXPAND;
2248 return 0;
2254 XAATiledFillChooser(GCPtr pGC)
2256 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
2257 PixmapPtr pPixmap = pGC->tile.pixmap;
2258 XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap);
2260 if(IS_OFFSCREEN_PIXMAP(pPixmap) && infoRec->FillCacheBltSpans &&
2261 CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) &&
2262 CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) &&
2263 CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) {
2265 return DO_PIXMAP_COPY;
2268 if(!(pPriv->flags & REDUCIBILITY_CHECKED) &&
2269 (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) {
2270 XAACheckTileReducibility(pPixmap,infoRec->CanDoMono8x8);
2273 if(pPriv->flags & REDUCIBLE_TO_8x8) {
2274 if((pPriv->flags & REDUCIBLE_TO_2_COLOR) && infoRec->CanDoMono8x8 &&
2275 !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) &&
2276 CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) &&
2277 CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) &&
2278 (!(infoRec->FillMono8x8PatternSpansFlags & RGB_EQUAL) ||
2279 (CHECK_RGB_EQUAL(pPriv->fg) && CHECK_RGB_EQUAL(pPriv->bg))) &&
2280 CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) {
2282 return DO_MONO_8x8;
2285 if(infoRec->CanDoColor8x8 &&
2286 CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) &&
2287 CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) &&
2288 CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) {
2290 return DO_COLOR_8x8;
2294 if(infoRec->UsingPixmapCache && infoRec->FillCacheBltSpans &&
2295 (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) &&
2296 (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) &&
2297 CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) &&
2298 CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) &&
2299 CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) {
2301 return DO_CACHE_BLT;
2304 if(infoRec->FillImageWriteRects &&
2305 CHECK_NO_GXCOPY(pGC,infoRec->FillImageWriteRectsFlags) &&
2306 CHECK_ROP(pGC,infoRec->FillImageWriteRectsFlags) &&
2307 CHECK_ROPSRC(pGC,infoRec->FillImageWriteRectsFlags) &&
2308 CHECK_PLANEMASK(pGC,infoRec->FillImageWriteRectsFlags)) {
2310 return DO_IMAGE_WRITE;
2313 return 0;
2317 static int RotateMasksX[8] = {
2318 0xFFFFFFFF, 0x7F7F7F7F, 0x3F3F3F3F, 0x1F1F1F1F,
2319 0x0F0F0F0F, 0x07070707, 0x03030303, 0x01010101
2322 static int RotateMasksY[4] = {
2323 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF
2326 void
2327 XAARotateMonoPattern(
2328 int *pat0, int *pat1,
2329 int xorg, int yorg,
2330 Bool msbfirst
2332 int tmp, mask;
2334 if(xorg) {
2335 if(msbfirst) xorg = 8 - xorg;
2336 mask = RotateMasksX[xorg];
2337 *pat0 = ((*pat0 >> xorg) & mask) | ((*pat0 << (8 - xorg)) & ~mask);
2338 *pat1 = ((*pat1 >> xorg) & mask) | ((*pat1 << (8 - xorg)) & ~mask);
2340 if(yorg >= 4) {
2341 tmp = *pat0; *pat0 = *pat1; *pat1 = tmp;
2342 yorg -= 4;
2344 if(yorg) {
2345 mask = RotateMasksY[yorg];
2346 yorg <<= 3;
2347 tmp = *pat0;
2348 *pat0 = ((*pat0 >> yorg) & mask) | ((*pat1 << (32 - yorg)) & ~mask);
2349 *pat1 = ((*pat1 >> yorg) & mask) | ((tmp << (32 - yorg)) & ~mask);
2355 void
2356 XAAInvalidatePixmapCache(ScreenPtr pScreen)
2358 XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
2359 XAAPixmapCachePrivatePtr pCachePriv =
2360 (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate;
2361 int i;
2363 if(!pCachePriv) return;
2365 for(i = 0; i < pCachePriv->Num512x512; i++)
2366 (pCachePriv->Info512)[i].serialNumber = 0;
2367 for(i = 0; i < pCachePriv->Num256x256; i++)
2368 (pCachePriv->Info256)[i].serialNumber = 0;
2369 for(i = 0; i < pCachePriv->Num128x128; i++)
2370 (pCachePriv->Info128)[i].serialNumber = 0;
2371 for(i = 0; i < pCachePriv->NumPartial; i++)
2372 (pCachePriv->InfoPartial)[i].serialNumber = 0;
2373 for(i = 0; i < pCachePriv->NumMono; i++)
2374 (pCachePriv->InfoMono)[i].serialNumber = 0;
2375 for(i = 0; i < pCachePriv->NumColor; i++)
2376 (pCachePriv->InfoColor)[i].serialNumber = 0;