From 1c94119ae26b94a60bb2c2b33494ed43c3b8a52f Mon Sep 17 00:00:00 2001 From: marha Date: Sun, 16 May 2010 20:50:58 +0000 Subject: svn merge -r588:HEAD ^/branches/released . --- xorg-server/hw/xfree86/xaa/xaaPCache.c | 4760 ++++++++++++++++---------------- 1 file changed, 2380 insertions(+), 2380 deletions(-) (limited to 'xorg-server/hw/xfree86/xaa/xaaPCache.c') diff --git a/xorg-server/hw/xfree86/xaa/xaaPCache.c b/xorg-server/hw/xfree86/xaa/xaaPCache.c index 7e3011bd5..62726d539 100644 --- a/xorg-server/hw/xfree86/xaa/xaaPCache.c +++ b/xorg-server/hw/xfree86/xaa/xaaPCache.c @@ -1,2380 +1,2380 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "gc.h" -#include "mi.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "regionstr.h" -#include "servermd.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaacexp.h" -#include "xaalocal.h" -#include "xaawrap.h" - -#define MAX_COLOR 32 -#define MAX_MONO 32 -#define MAX_8 32 -#define MAX_128 32 -#define MAX_256 32 -#define MAX_512 16 - -static int CacheInitIndex = -1; -#define CACHEINIT(p) ((p)->privates[CacheInitIndex].val) - - -typedef struct _CacheLink { - int x; - int y; - int w; - int h; - struct _CacheLink *next; -} CacheLink, *CacheLinkPtr; - - -static void -TransferList(CacheLinkPtr list, XAACacheInfoPtr array, int num) -{ - while(num--) { - array->x = list->x; - array->y = list->y; - array->w = list->w; - array->h = list->h; - array->serialNumber = 0; - array->fg = array->bg = -1; - list = list->next; - array++; - } -} - - - -static CacheLinkPtr -Enlist(CacheLinkPtr link, int x, int y, int w, int h) -{ - CacheLinkPtr newLink; - - newLink = xalloc(sizeof(CacheLink)); - newLink->next = link; - newLink->x = x; newLink->y = y; - newLink->w = w; newLink->h = h; - return newLink; -} - - - -static CacheLinkPtr -Delist(CacheLinkPtr link) { - CacheLinkPtr ret = NULL; - - if(link) { - ret = link->next; - xfree(link); - } - return ret; -} - - - -static void -FreeList(CacheLinkPtr link) { - CacheLinkPtr tmp; - - while(link) { - tmp = link; - link = link->next; - xfree(tmp); - } -} - - - -static CacheLinkPtr -QuadLinks(CacheLinkPtr big, CacheLinkPtr little) -{ - /* CAUTION: This doesn't free big */ - int w1, w2, h1, h2; - - while(big) { - w1 = big->w >> 1; - w2 = big->w - w1; - h1 = big->h >> 1; - h2 = big->h - h1; - - little = Enlist(little, big->x, big->y, w1, h1); - little = Enlist(little, big->x + w1, big->y, w2, h1); - little = Enlist(little, big->x, big->y + h1, w1, h2); - little = Enlist(little, big->x + w1, big->y + h1, w2, h2); - - big = big->next; - } - return little; -} - - -static void -SubdivideList(CacheLinkPtr *large, CacheLinkPtr *small) -{ - CacheLinkPtr big = *large; - CacheLinkPtr little = *small; - int size = big->w >> 1; - - little = Enlist(little, big->x, big->y, size, size); - little = Enlist(little, big->x + size, big->y, size, size); - little = Enlist(little, big->x, big->y + size, size, size); - little = Enlist(little, big->x + size, big->y + size, size, size); - *small = little; - big = Delist(big); - *large = big; -} - -static void -FreePixmapCachePrivate(XAAPixmapCachePrivatePtr pPriv) -{ - if(!pPriv) return; - - if(pPriv->Info512) - xfree(pPriv->Info512); - if(pPriv->Info256) - xfree(pPriv->Info256); - if(pPriv->Info128) - xfree(pPriv->Info128); - if(pPriv->InfoColor) - xfree(pPriv->InfoColor); - if(pPriv->InfoMono) - xfree(pPriv->InfoMono); - if(pPriv->InfoPartial) - xfree(pPriv->InfoPartial); - - xfree(pPriv); -} - -void -XAAClosePixmapCache(ScreenPtr pScreen) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - - if(infoRec->PixmapCachePrivate) - FreePixmapCachePrivate( - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate); - - infoRec->PixmapCachePrivate = NULL; -} - - - -static CacheLinkPtr -ThinOutPartials( - CacheLinkPtr ListPartial, - int *num, int *maxw, int *maxh -) { -/* This guy's job is to get at least 4 big slots out of a list of fragments */ - - CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; - int Num64, Num32, Num16, Num8, NumKeepers; - int w, h; - - List64 = List32 = List16 = List8 = ListKeepers = NULL; - Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; - w = h = 0; - - /* We sort partials by how large a square tile they can cache. - If a partial can't store a 64x64, 32x32, 16x16 or 8x8 tile, - we free it. */ - - pCur = ListPartial; - while(pCur) { - next = pCur->next; - if((pCur->w >= 64) && (pCur->h >= 64)) { - pCur->next = List64; List64 = pCur; - Num64++; - } else - if((pCur->w >= 32) && (pCur->h >= 32)) { - pCur->next = List32; List32 = pCur; - Num32++; - } else - if((pCur->w >= 16) && (pCur->h >= 16)) { - pCur->next = List16; List16 = pCur; - Num16++; - } else - if((pCur->w >= 8) && (pCur->h >= 8)) { - pCur->next = List8; List8 = pCur; - Num8++; - } else { - xfree(pCur); - } - - pCur = next; - } - - /* We save all the tiles from the largest bin that we can get - at least 4 of. If there are too few of a bigger slot, we - cut it in fourths to make smaller slots. */ - - if(Num64 >= 4) { - ListKeepers = List64; List64 = NULL; - NumKeepers = Num64; - goto GOT_EM; - } else if(Num64) { - List32 = QuadLinks(List64, List32); - Num32 += Num64 * 4; - Num64 = 0; - } - - if(Num32 >= 4) { - ListKeepers = List32; List32 = NULL; - NumKeepers = Num32; - goto GOT_EM; - } else if(Num32) { - List16 = QuadLinks(List32, List16); - Num16 += Num32 * 4; - Num32 = 0; - } - - if(Num16 >= 4) { - ListKeepers = List16; List16 = NULL; - NumKeepers = Num16; - goto GOT_EM; - } else if(Num16) { - List8 = QuadLinks(List16, List8); - Num8 += Num16 * 4; - Num16 = 0; - } - - if(Num8 >= 4) { - ListKeepers = List8; List8 = NULL; - NumKeepers = Num8; - goto GOT_EM; - } - -GOT_EM: - - /* Free the ones we aren't using */ - - if(List64) FreeList(List64); - if(List32) FreeList(List32); - if(List16) FreeList(List16); - if(List8) FreeList(List8); - - - /* Enlarge the slots if we can */ - - if(ListKeepers) { - CacheLinkPtr pLink = ListKeepers; - w = h = 128; - - while(pLink) { - if(pLink->w < w) w = pLink->w; - if(pLink->h < h) h = pLink->h; - pLink = pLink->next; - } - } - - *maxw = w; - *maxh = h; - *num = NumKeepers; - return ListKeepers; -} - -static void -ConvertColorToMono( - CacheLinkPtr *ColorList, - int ColorW, int ColorH, - CacheLinkPtr *MonoList, - int MonoW, int MonoH -){ - int x, y, w; - - x = (*ColorList)->x; y = (*ColorList)->y; - *ColorList = Delist(*ColorList); - - while(ColorH) { - ColorH -= MonoH; - for(w = 0; w <= (ColorW - MonoW); w += MonoW) - *MonoList = Enlist(*MonoList, x + w, y + ColorH, MonoW, MonoH); - } -} - -static void -ConvertAllPartialsTo8x8( - int *NumMono, int *NumColor, - CacheLinkPtr ListPartial, - CacheLinkPtr *ListMono, - CacheLinkPtr *ListColor, - XAAInfoRecPtr infoRec -){ -/* This guy extracts as many 8x8 slots as it can out of fragments */ - - int ColorH = infoRec->CacheHeightColor8x8Pattern; - int ColorW = infoRec->CacheWidthColor8x8Pattern; - int MonoH = infoRec->CacheHeightMono8x8Pattern; - int MonoW = infoRec->CacheWidthMono8x8Pattern; - int x, y, w, Height, Width; - Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); - Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); - CacheLinkPtr pLink = ListPartial; - CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; - - if(DoColor && DoMono) { - /* we assume color patterns take more space than color ones */ - if(MonoH > ColorH) ColorH = MonoH; - if(MonoW > ColorW) ColorW = MonoW; - } - - /* Break up the area into as many Color and Mono slots as we can */ - - while(pLink) { - Height = pLink->h; - Width = pLink->w; - x = pLink->x; - y = pLink->y; - - if(DoColor) { - while(Height >= ColorH) { - Height -= ColorH; - for(w = 0; w <= (Width - ColorW); w += ColorW) { - ColorList = Enlist( - ColorList, x + w, y + Height, ColorW, ColorH); - (*NumColor)++; - } - } - } - - if(DoMono && (Height >= MonoH)) { - while(Height >= MonoH) { - Height -= MonoH; - for(w = 0; w <= (Width - MonoW); w += MonoW) { - MonoList = Enlist( - MonoList, x + w, y + Height, MonoW, MonoH); - (*NumMono)++; - } - } - } - - pLink = pLink->next; - } - - - *ListMono = MonoList; - *ListColor = ColorList; - FreeList(ListPartial); -} - - -static CacheLinkPtr -ExtractOneThatFits(CacheLinkPtr *initList, int w, int h) -{ - CacheLinkPtr list = *initList; - CacheLinkPtr prev = NULL; - - while(list) { - if((list->w >= w) && (list->h >= h)) - break; - prev = list; - list = list->next; - } - - if(list) { - if(prev) - prev->next = list->next; - else - *initList = list->next; - - list->next = NULL; - } - - return list; -} - - -static CacheLinkPtr -ConvertSomePartialsTo8x8( - int *NumMono, int *NumColor, int *NumPartial, - CacheLinkPtr ListPartial, - CacheLinkPtr *ListMono, - CacheLinkPtr *ListColor, - int *maxw, int *maxh, - XAAInfoRecPtr infoRec -){ -/* This guy tries to get 4 of each type of 8x8 slot requested out of - a list of fragments all while trying to retain some big fragments - for the cache blits */ - - int ColorH = infoRec->CacheHeightColor8x8Pattern; - int ColorW = infoRec->CacheWidthColor8x8Pattern; - int MonoH = infoRec->CacheHeightMono8x8Pattern; - int MonoW = infoRec->CacheWidthMono8x8Pattern; - Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); - Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); - CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; - CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; - int Num64, Num32, Num16, Num8, NumKeepers; - int w, h, Width, Height; - int MonosPerColor = 1; - - if(DoColor && DoMono) { - /* we assume color patterns take more space than color ones */ - if(MonoH > ColorH) ColorH = MonoH; - if(MonoW > ColorW) ColorW = MonoW; - MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW); - } - - List64 = List32 = List16 = List8 = ListKeepers = MonoList = ColorList = NULL; - Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; - Width = Height = 0; - - /* We sort partials by how large a square tile they can cache. - We make 8x8 patterns from the leftovers if we can. */ - - pCur = ListPartial; - while(pCur) { - next = pCur->next; - if((pCur->w >= 64) && (pCur->h >= 64)) { - pCur->next = List64; List64 = pCur; - Num64++; - } else - if((pCur->w >= 32) && (pCur->h >= 32)) { - pCur->next = List32; List32 = pCur; - Num32++; - } else - if((pCur->w >= 16) && (pCur->h >= 16)) { - pCur->next = List16; List16 = pCur; - Num16++; - } else - if((pCur->w >= 8) && (pCur->h >= 8)) { - pCur->next = List8; List8 = pCur; - Num8++; - } else { - h = pCur->h; - if(DoColor && (pCur->w >= ColorW) && (h >= ColorH)) { - while(h >= ColorH) { - h -= ColorH; - for(w = 0; w <= (pCur->w - ColorW); w += ColorW) { - ColorList = Enlist( ColorList, - pCur->x + w, pCur->y + h, ColorW, ColorH); - (*NumColor)++; - } - } - } - if(DoMono && (pCur->w >= MonoW) && (h >= MonoH)) { - while(h >= MonoH) { - h -= MonoH; - for(w = 0; w <= (pCur->w - MonoW); w += MonoW) { - MonoList = Enlist( MonoList, - pCur->x + w, pCur->y + h, MonoW, MonoH); - (*NumMono)++; - } - } - } - xfree(pCur); - } - - pCur = next; - } - - /* Try to extract at least 4 of each type of 8x8 slot that we need */ - - if(DoColor) { - CacheLinkPtr theOne; - while(*NumColor < 4) { - theOne = NULL; - if(Num8) { - if((theOne = ExtractOneThatFits(&List8, ColorW, ColorH))) - Num8--; - } - if(Num16 && !theOne) { - if((theOne = ExtractOneThatFits(&List16, ColorW, ColorH))) - Num16--; - } - if(Num32 && !theOne) { - if((theOne = ExtractOneThatFits(&List32, ColorW, ColorH))) - Num32--; - } - if(Num64 && !theOne) { - if((theOne = ExtractOneThatFits(&List64, ColorW, ColorH))) - Num64--; - } - - if(!theOne) break; - - - ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, - &MonoList, &ColorList, infoRec); - - if(DoMono) { - while(*NumColor && (*NumMono < 4)) { - ConvertColorToMono(&ColorList, ColorW, ColorH, - &MonoList, MonoW, MonoH); - (*NumColor)--; *NumMono += MonosPerColor; - } - } - } - } - - if(DoMono) { - CacheLinkPtr theOne; - while(*NumMono < 4) { - theOne = NULL; - if(Num8) { - if((theOne = ExtractOneThatFits(&List8, MonoW, MonoH))) - Num8--; - } - if(Num16 && !theOne) { - if((theOne = ExtractOneThatFits(&List16, MonoW, MonoH))) - Num16--; - } - if(Num32 && !theOne) { - if((theOne = ExtractOneThatFits(&List32, MonoW, MonoH))) - Num32--; - } - if(Num64 && !theOne) { - if((theOne = ExtractOneThatFits(&List64, MonoW, MonoH))) - Num64--; - } - - if(!theOne) break; - - ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, - &MonoList, &ColorList, infoRec); - } - } - - /* We save all the tiles from the largest bin that we can get - at least 4 of. If there are too few of a bigger slot, we - cut it in fourths to make smaller slots. */ - - if(Num64 >= 4) { - ListKeepers = List64; List64 = NULL; - NumKeepers = Num64; - goto GOT_EM; - } else if(Num64) { - List32 = QuadLinks(List64, List32); - Num32 += Num64 * 4; - Num64 = 0; - } - - if(Num32 >= 4) { - ListKeepers = List32; List32 = NULL; - NumKeepers = Num32; - goto GOT_EM; - } else if(Num32) { - List16 = QuadLinks(List32, List16); - Num16 += Num32 * 4; - Num32 = 0; - } - - if(Num16 >= 4) { - ListKeepers = List16; List16 = NULL; - NumKeepers = Num16; - goto GOT_EM; - } else if(Num16) { - List8 = QuadLinks(List16, List8); - Num8 += Num16 * 4; - Num16 = 0; - } - - if(Num8 >= 4) { - ListKeepers = List8; List8 = NULL; - NumKeepers = Num8; - goto GOT_EM; - } - -GOT_EM: - - /* Free the ones we aren't using */ - - if(List64) - ConvertAllPartialsTo8x8(NumMono, NumColor, List64, - &MonoList, &ColorList, infoRec); - if(List32) - ConvertAllPartialsTo8x8(NumMono, NumColor, List32, - &MonoList, &ColorList, infoRec); - if(List16) - ConvertAllPartialsTo8x8(NumMono, NumColor, List16, - &MonoList, &ColorList, infoRec); - if(List8) - ConvertAllPartialsTo8x8(NumMono, NumColor, List8, - &MonoList, &ColorList, infoRec); - - - /* Enlarge the slots if we can */ - - if(ListKeepers) { - CacheLinkPtr pLink = ListKeepers; - Width = Height = 128; - - while(pLink) { - if(pLink->w < Width) Width = pLink->w; - if(pLink->h < Height) Height = pLink->h; - pLink = pLink->next; - } - } - - *ListMono = MonoList; - *ListColor = ColorList; - *maxw = Width; - *maxh = Height; - *NumPartial = NumKeepers; - return ListKeepers; -} - - -void -XAAInitPixmapCache( - ScreenPtr pScreen, - RegionPtr areas, - pointer data -) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XAAInfoRecPtr infoRec = (XAAInfoRecPtr)data; - XAAPixmapCachePrivatePtr pCachePriv; - BoxPtr pBox = REGION_RECTS(areas); - int nBox = REGION_NUM_RECTS(areas); - int Num512, Num256, Num128, NumPartial, NumColor, NumMono; - int Target512, Target256; - CacheLinkPtr List512, List256, List128, ListPartial, ListColor, ListMono; - int x, y, w, h, ntotal, granularity, width, height, i; - int MaxPartialWidth, MaxPartialHeight; - - infoRec->MaxCacheableTileWidth = 0; - infoRec->MaxCacheableTileHeight = 0; - infoRec->MaxCacheableStippleHeight = 0; - infoRec->MaxCacheableStippleWidth = 0; - infoRec->UsingPixmapCache = FALSE; - - - if(!nBox || !pBox || !(infoRec->Flags & PIXMAP_CACHE)) - return; - - /* Allocate a persistent per-screen init flag to control messages */ - if (CacheInitIndex < 0) - CacheInitIndex = xf86AllocateScrnInfoPrivateIndex(); - - /* free the old private data if it exists */ - if(infoRec->PixmapCachePrivate) { - FreePixmapCachePrivate( - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate); - infoRec->PixmapCachePrivate = NULL; - } - - Num512 = Num256 = Num128 = NumPartial = NumMono = NumColor = 0; - List512 = List256 = List128 = ListPartial = ListMono = ListColor = NULL; - granularity = infoRec->CachePixelGranularity; - if(granularity <= 1) granularity = 0; - - /* go through the boxes and break it into as many pieces as we can fit */ - - while(nBox--) { - x = pBox->x1; - if(granularity) { - int tmp = x % granularity; - if(tmp) x += (granularity - tmp); - } - width = pBox->x2 - x; - if(width <= 0) {pBox++; continue;} - - y = pBox->y1; - height = pBox->y2 - y; - - for(h = 0; h <= (height - 512); h += 512) { - for(w = 0; w <= (width - 512); w += 512) { - List512 = Enlist(List512, x + w, y + h, 512, 512); - Num512++; - } - for(; w <= (width - 256); w += 256) { - List256 = Enlist(List256, x + w, y + h, 256, 256); - List256 = Enlist(List256, x + w, y + h + 256, 256, 256); - Num256 += 2; - } - for(; w <= (width - 128); w += 128) { - List128 = Enlist(List128, x + w, y + h, 128, 128); - List128 = Enlist(List128, x + w, y + h + 128, 128, 128); - List128 = Enlist(List128, x + w, y + h + 256, 128, 128); - List128 = Enlist(List128, x + w, y + h + 384, 128, 128); - Num128 += 4; - } - if(w < width) { - int d = width - w; - ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); - ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); - ListPartial = Enlist(ListPartial, x + w, y + h + 256, d, 128); - ListPartial = Enlist(ListPartial, x + w, y + h + 384, d, 128); - NumPartial += 4; - } - } - for(; h <= (height - 256); h += 256) { - for(w = 0; w <= (width - 256); w += 256) { - List256 = Enlist(List256, x + w, y + h, 256, 256); - Num256++; - } - for(; w <= (width - 128); w += 128) { - List128 = Enlist(List128, x + w, y + h, 128, 128); - List128 = Enlist(List128, x + w, y + h + 128, 128, 128); - Num128 += 2; - } - if(w < width) { - int d = width - w; - ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); - ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); - NumPartial += 2; - } - } - for(; h <= (height - 128); h += 128) { - for(w = 0; w <= (width - 128); w += 128) { - List128 = Enlist(List128, x + w, y + h, 128, 128); - Num128++; - } - if(w < width) { - ListPartial = Enlist( - ListPartial, x + w, y + h, width - w, 128); - NumPartial++; - } - } - if(h < height) { - int d = height - h; - for(w = 0; w <= (width - 128); w += 128) { - ListPartial = Enlist(ListPartial, x + w, y + h, 128, d); - NumPartial++; - } - if(w < width) { - ListPartial = Enlist(ListPartial, x + w, y + h, width - w, d); - NumPartial++; - } - } - pBox++; - } - - -/* - by this point we've carved the space into as many 512x512, 256x256 - and 128x128 blocks as we could fit. We will then break larger - blocks into smaller ones if we need to. The rules are as follows: - - 512x512 - - 1) Don't take up more than half the memory. - 2) Don't bother if you can't get at least four. - 3) Don't make more than MAX_512. - 4) Don't have any of there are no 256x256s. - - 256x256 - - 1) Don't take up more than a quarter of the memory enless there - aren't any 512x512s. Then we can take up to half. - 2) Don't bother if you can't get at least four. - 3) Don't make more than MAX_256. - - 128x128 - - 1) Don't make more than MAX_128. - - We don't bother with the partial blocks unless we can use them - for 8x8 pattern fills or we are short on larger blocks. - -*/ - - ntotal = Num128 + (Num256<<2) + (Num512<<4); - - Target512 = ntotal >> 5; - if(Target512 < 4) Target512 = 0; - if(!Target512) Target256 = ntotal >> 3; - else Target256 = ntotal >> 4; - if(Target256 < 4) Target256 = 0; - - if(Num512 && Num256 < 4) { - while(Num512 && Num256 < Target256) { - SubdivideList(&List512, &List256); - Num256 += 4; Num512--; - } - } - - if(!Num512) { /* no room */ - } else if((Num512 < 4) || (!Target512)) { - while(Num512) { - SubdivideList(&List512, &List256); - Num256 += 4; Num512--; - } - } else if((Num512 > MAX_512) || (Num512 > Target512)){ - while(Num512 > MAX_512) { - SubdivideList(&List512, &List256); - Num256 += 4; Num512--; - } - while(Num512 > Target512) { - if(Num256 < MAX_256) { - SubdivideList(&List512, &List256); - Num256 += 4; Num512--; - } else break; - } - } - - if(!Num256) { /* no room */ - } else if((Num256 < 4) || (!Target256)) { - while(Num256) { - SubdivideList(&List256, &List128); - Num128 += 4; Num256--; - } - } else if((Num256 > MAX_256) || (Num256 > Target256)) { - while(Num256 > MAX_256) { - SubdivideList(&List256, &List128); - Num128 += 4; Num256--; - } - while(Num256 > Target256) { - if(Num128 < MAX_128) { - SubdivideList(&List256, &List128); - Num128 += 4; Num256--; - } else break; - } - } - - if(Num128 && ((Num128 < 4) || (Num128 > MAX_128))) { - CacheLinkPtr next; - int max = (Num128 > MAX_128) ? MAX_128 : 0; - - /* - * Note: next is set in this way to work around a code generation - * bug in gcc 2.7.2.3. - */ - next = List128->next; - while(Num128 > max) { - List128->next = ListPartial; - ListPartial = List128; - if((List128 = next)) - next = List128->next; - NumPartial++; Num128--; - } - } - - MaxPartialHeight = MaxPartialWidth = 0; - - /* at this point we have as many 512x512 and 256x256 slots as we - want but may have an excess of 128x128 slots. We still need - to find out if we need 8x8 slots. We take these from the - partials if we have them. Otherwise, we break some 128x128's */ - - if(!(infoRec->PixmapCacheFlags & (CACHE_MONO_8x8 | CACHE_COLOR_8x8))) { - if(NumPartial) { - if(Num128) { /* don't bother with partials */ - FreeList(ListPartial); - NumPartial = 0; ListPartial = NULL; - } else { - /* We have no big slots. Weed out the unusable partials */ - ListPartial = ThinOutPartials(ListPartial, &NumPartial, - &MaxPartialWidth, &MaxPartialHeight); - } - } - } else { - int MonosPerColor = 1; - int ColorH = infoRec->CacheHeightColor8x8Pattern; - int ColorW = infoRec->CacheWidthColor8x8Pattern; - int MonoH = infoRec->CacheHeightMono8x8Pattern; - int MonoW = infoRec->CacheWidthMono8x8Pattern; - Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); - Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); - - if(DoColor) infoRec->CanDoColor8x8 = FALSE; - if(DoMono) infoRec->CanDoMono8x8 = FALSE; - - if(DoColor && DoMono) { - /* we assume color patterns take more space than color ones */ - if(MonoH > ColorH) ColorH = MonoH; - if(MonoW > ColorW) ColorW = MonoW; - MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW); - } - - if(Num128) { - if(NumPartial) { /* use all for 8x8 slots */ - ConvertAllPartialsTo8x8(&NumMono, &NumColor, - ListPartial, &ListMono, &ListColor, infoRec); - NumPartial = 0; ListPartial = NULL; - } - - /* Get some 8x8 slots from the 128 slots */ - while((Num128 > 4) && - ((NumMono < MAX_MONO) && (NumColor < MAX_COLOR))) { - CacheLinkPtr tmp = NULL; - - tmp = Enlist(tmp, List128->x, List128->y, - List128->w, List128->h); - List128 = Delist(List128); - Num128--; - - ConvertAllPartialsTo8x8(&NumMono, &NumColor, - tmp, &ListMono, &ListColor, infoRec); - } - } else if(NumPartial) { - /* We have share partials between 8x8 slots and tiles. */ - ListPartial = ConvertSomePartialsTo8x8(&NumMono, &NumColor, - &NumPartial, ListPartial, &ListMono, &ListColor, - &MaxPartialWidth, &MaxPartialHeight, infoRec); - } - - - if(DoMono && DoColor) { - if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { - int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; - - while(NumColor > max) { - ConvertColorToMono(&ListColor, ColorW, ColorH, - &ListMono, MonoW, MonoH); - NumColor--; NumMono += MonosPerColor; - } - } - - /* favor Mono slots over Color ones */ - while((NumColor > 4) && (NumMono < MAX_MONO)) { - ConvertColorToMono(&ListColor, ColorW, ColorH, - &ListMono, MonoW, MonoH); - NumColor--; NumMono += MonosPerColor; - } - } - - if(NumMono && ((NumMono > MAX_MONO) || (NumMono < 4))) { - int max = (NumMono > MAX_MONO) ? MAX_MONO : 0; - - while(NumMono > max) { - ListMono = Delist(ListMono); - NumMono--; - } - } - if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { - int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; - - while(NumColor > max) { - ListColor = Delist(ListColor); - NumColor--; - } - } - } - - - pCachePriv = xcalloc(1,sizeof(XAAPixmapCachePrivate)); - if(!pCachePriv) { - if(Num512) FreeList(List512); - if(Num256) FreeList(List256); - if(Num128) FreeList(List128); - if(NumPartial) FreeList(ListPartial); - if(NumColor) FreeList(ListColor); - if(NumMono) FreeList(ListMono); - return; - } - - infoRec->PixmapCachePrivate = (char*)pCachePriv; - - if(Num512) { - pCachePriv->Info512 = xcalloc(Num512,sizeof(XAACacheInfoRec)); - if(!pCachePriv->Info512) Num512 = 0; - if(Num512) TransferList(List512, pCachePriv->Info512, Num512); - FreeList(List512); - pCachePriv->Num512x512 = Num512; - } - if(Num256) { - pCachePriv->Info256 = xcalloc(Num256, sizeof(XAACacheInfoRec)); - if(!pCachePriv->Info256) Num256 = 0; - if(Num256) TransferList(List256, pCachePriv->Info256, Num256); - FreeList(List256); - pCachePriv->Num256x256 = Num256; - } - if(Num128) { - pCachePriv->Info128 = xcalloc(Num128, sizeof(XAACacheInfoRec)); - if(!pCachePriv->Info128) Num128 = 0; - if(Num128) TransferList(List128, pCachePriv->Info128, Num128); - FreeList(List128); - pCachePriv->Num128x128 = Num128; - } - - if(NumPartial) { - pCachePriv->InfoPartial = xcalloc(NumPartial, sizeof(XAACacheInfoRec)); - if(!pCachePriv->InfoPartial) NumPartial = 0; - if(NumPartial) - TransferList(ListPartial, pCachePriv->InfoPartial, NumPartial); - FreeList(ListPartial); - pCachePriv->NumPartial = NumPartial; - } - - if(NumColor) { - pCachePriv->InfoColor = xcalloc(NumColor, sizeof(XAACacheInfoRec)); - if(!pCachePriv->InfoColor) NumColor = 0; - if(NumColor) TransferList(ListColor, pCachePriv->InfoColor, NumColor); - FreeList(ListColor); - pCachePriv->NumColor = NumColor; - } - - if(NumMono) { - pCachePriv->InfoMono = xcalloc(NumMono, sizeof(XAACacheInfoRec)); - if(!pCachePriv->InfoMono) NumMono = 0; - if(NumMono) TransferList(ListMono, pCachePriv->InfoMono, NumMono); - FreeList(ListMono); - pCachePriv->NumMono = NumMono; - } - - - if(NumPartial) { - infoRec->MaxCacheableTileWidth = MaxPartialWidth; - infoRec->MaxCacheableTileHeight = MaxPartialHeight; - } - if(Num128) - infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 128; - if(Num256) - infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 256; - if(Num512) - infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 512; - - - infoRec->MaxCacheableStippleHeight = infoRec->MaxCacheableTileHeight; - infoRec->MaxCacheableStippleWidth = - infoRec->MaxCacheableTileWidth * pScrn->bitsPerPixel; - if(infoRec->ScreenToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) - infoRec->MaxCacheableStippleWidth /= 3; - - if(NumMono) { - if(!(infoRec->Mono8x8PatternFillFlags & - (HARDWARE_PATTERN_PROGRAMMED_ORIGIN | - HARDWARE_PATTERN_PROGRAMMED_BITS))) { - int numPerLine = - infoRec->CacheWidthMono8x8Pattern/infoRec->MonoPatternPitch; - - for(i = 0; i < 64; i++) { - pCachePriv->MonoOffsets[i].y = i/numPerLine; - pCachePriv->MonoOffsets[i].x = (i % numPerLine) * - infoRec->MonoPatternPitch; - } - } - infoRec->CanDoMono8x8 = TRUE; - } - if(NumColor) { - if(!(infoRec->Color8x8PatternFillFlags & - HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { - - for(i = 0; i < 64; i++) { - pCachePriv->ColorOffsets[i].y = i & 0x07; - pCachePriv->ColorOffsets[i].x = i & ~0x07; - } - } - infoRec->CanDoColor8x8 = TRUE; - } - - if(!CACHEINIT(pScrn)) { - xf86ErrorF("\tSetting up tile and stipple cache:\n"); - if(NumPartial) - xf86ErrorF("\t\t%i %ix%i slots\n", - NumPartial, MaxPartialWidth, MaxPartialHeight); - if(Num128) xf86ErrorF("\t\t%i 128x128 slots\n", Num128); - if(Num256) xf86ErrorF("\t\t%i 256x256 slots\n", Num256); - if(Num512) xf86ErrorF("\t\t%i 512x512 slots\n", Num512); - if(NumColor) xf86ErrorF("\t\t%i 8x8 color pattern slots\n", NumColor); - if(NumMono) xf86ErrorF("\t\t%i 8x8 color expansion slots\n", NumMono); - } - - if(!(NumPartial | Num128 | Num256 | Num512 | NumColor | NumMono)) { - if(!CACHEINIT(pScrn)) - xf86ErrorF("\t\tNot enough video memory for pixmap cache\n"); - } else infoRec->UsingPixmapCache = TRUE; - - CACHEINIT(pScrn) = 1; -} - -#if X_BYTE_ORDER == X_BIG_ENDIAN -static CARD32 StippleMasks[4] = { - 0x80808080, - 0xC0C0C0C0, - 0x00000000, - 0xF0F0F0F0 -}; -#else -static CARD32 StippleMasks[4] = { - 0x01010101, - 0x03030303, - 0x00000000, - 0x0F0F0F0F -}; -#endif - -Bool -XAACheckStippleReducibility(PixmapPtr pPixmap) -{ - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); - CARD32 *IntPtr = (CARD32*)pPixmap->devPrivate.ptr; - int w = pPixmap->drawable.width; - int h = pPixmap->drawable.height; - int i; - CARD32 bits[8]; - CARD32 mask = SHIFT_R(0xFFFFFFFF,24); - - pPriv->flags |= REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR; - pPriv->flags &= ~REDUCIBLE_TO_8x8; - - if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) - return FALSE; - - i = (h > 8) ? 8 : h; - - switch(w) { - case 32: - while(i--) { - bits[i] = IntPtr[i] & mask; - if( (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask, 8)), 8)) || - (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,16)),16)) || - (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,24)),24))) - return FALSE; - } - break; - case 16: - while(i--) { - bits[i] = IntPtr[i] & mask; - if(bits[i] != ((IntPtr[i] & SHIFT_R(SHIFT_L(mask,8),8)))) - return FALSE; - } - break; - default: - while(i--) - bits[i] = IntPtr[i] & mask; - break; - } - - switch(h) { - case 32: - if( (IntPtr[8] != IntPtr[16]) || (IntPtr[9] != IntPtr[17]) || - (IntPtr[10] != IntPtr[18]) || (IntPtr[11] != IntPtr[19]) || - (IntPtr[12] != IntPtr[20]) || (IntPtr[13] != IntPtr[21]) || - (IntPtr[14] != IntPtr[22]) || (IntPtr[15] != IntPtr[23]) || - (IntPtr[16] != IntPtr[24]) || (IntPtr[17] != IntPtr[25]) || - (IntPtr[18] != IntPtr[26]) || (IntPtr[19] != IntPtr[27]) || - (IntPtr[20] != IntPtr[28]) || (IntPtr[21] != IntPtr[29]) || - (IntPtr[22] != IntPtr[30]) || (IntPtr[23] != IntPtr[31])) - return FALSE; - /* fall through */ - case 16: - if( (IntPtr[0] != IntPtr[8]) || (IntPtr[1] != IntPtr[9]) || - (IntPtr[2] != IntPtr[10]) || (IntPtr[3] != IntPtr[11]) || - (IntPtr[4] != IntPtr[12]) || (IntPtr[5] != IntPtr[13]) || - (IntPtr[6] != IntPtr[14]) || (IntPtr[7] != IntPtr[15])) - return FALSE; - case 8: break; - case 1: bits[1] = bits[0]; - case 2: bits[2] = bits[0]; bits[3] = bits[1]; - case 4: bits[4] = bits[0]; bits[5] = bits[1]; - bits[6] = bits[2]; bits[7] = bits[3]; - break; - } - - pPriv->flags |= REDUCIBLE_TO_8x8; - - pPriv->pattern0 = bits[0] | SHIFT_L(bits[1],8) | SHIFT_L(bits[2],16) | SHIFT_L(bits[3],24); - pPriv->pattern1 = bits[4] | SHIFT_L(bits[5],8) | SHIFT_L(bits[6],16) | SHIFT_L(bits[7],24); - - if(w < 8) { - pPriv->pattern0 &= StippleMasks[w - 1]; - pPriv->pattern1 &= StippleMasks[w - 1]; - - switch(w) { - case 1: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,1); - pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,1); - case 2: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,2); - pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,2); - case 4: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,4); - pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,4); - } - } - - if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { - pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); - pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); - } - - - return TRUE; -} - - -Bool -XAACheckTileReducibility(PixmapPtr pPixmap, Bool checkMono) -{ - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); - CARD32 *IntPtr; - int w = pPixmap->drawable.width; - int h = pPixmap->drawable.height; - int pitch = pPixmap->devKind >> 2; - int dwords, i, j; - - pPriv->flags |= REDUCIBILITY_CHECKED; - pPriv->flags &= ~(REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR); - - if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) - return FALSE; - - dwords = ((w * pPixmap->drawable.bitsPerPixel) + 31) >> 5; - i = (h > 8) ? 8 : h; - - - if(w > 8) { - IntPtr = (CARD32*)pPixmap->devPrivate.ptr; - switch(pPixmap->drawable.bitsPerPixel) { - case 8: - while(i--) { - for(j = 2; j < dwords; j++) - if(IntPtr[j] != IntPtr[j & 0x01]) - return FALSE; - IntPtr += pitch; - } - break; - case 16: - while(i--) { - for(j = 4; j < dwords; j++) - if(IntPtr[j] != IntPtr[j & 0x03]) - return FALSE; - IntPtr += pitch; - } - break; - case 24: - while(i--) { - for(j = 6; j < dwords; j++) - if(IntPtr[j] != IntPtr[j % 6]) - return FALSE; - IntPtr += pitch; - } - break; - case 32: - while(i--) { - for(j = 8; j < dwords; j++) - if(IntPtr[j] != IntPtr[j & 0x07]) - return FALSE; - IntPtr += pitch; - } - break; - default: return FALSE; - } - - } - - - if(h == 32) { - CARD32 *IntPtr2, *IntPtr3, *IntPtr4; - i = 8; - IntPtr = (CARD32*)pPixmap->devPrivate.ptr; - IntPtr2 = IntPtr + (pitch << 3); - IntPtr3 = IntPtr2 + (pitch << 3); - IntPtr4 = IntPtr3 + (pitch << 3); - while(i--) { - for(j = 0; j < dwords; j++) - if((IntPtr[j] != IntPtr2[j]) || (IntPtr[j] != IntPtr3[j]) || - (IntPtr[j] != IntPtr4[j])) - return FALSE; - IntPtr += pitch; - IntPtr2 += pitch; - IntPtr3 += pitch; - IntPtr4 += pitch; - } - } else if (h == 16) { - CARD32 *IntPtr2; - i = 8; - IntPtr = (CARD32*)pPixmap->devPrivate.ptr; - IntPtr2 = IntPtr + (pitch << 3); - while(i--) { - for(j = 0; j < dwords; j++) - if(IntPtr[j] != IntPtr2[j]) - return FALSE; - IntPtr += pitch; - IntPtr2 += pitch; - } - } - - pPriv->flags |= REDUCIBLE_TO_8x8; - - if(checkMono) { - XAAInfoRecPtr infoRec = - GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); - unsigned char bits[8]; - int fg, bg = -1, x, y; - - i = (h > 8) ? 8 : h; - j = (w > 8) ? 8 : w; - - if(pPixmap->drawable.bitsPerPixel == 8) { - unsigned char *srcp = pPixmap->devPrivate.ptr; - fg = srcp[0]; - pitch = pPixmap->devKind; - for(y = 0; y < i; y++) { - bits[y] = 0; - for(x = 0; x < j; x++) { - if(srcp[x] != fg) { - if(bg == -1) bg = srcp[x]; - else if(bg != srcp[x]) return TRUE; - } else bits[y] |= 1 << x; - } - srcp += pitch; - } - } else if(pPixmap->drawable.bitsPerPixel == 16) { - unsigned short *srcp = (unsigned short*)pPixmap->devPrivate.ptr; - fg = srcp[0]; - pitch = pPixmap->devKind >> 1; - for(y = 0; y < i; y++) { - bits[y] = 0; - for(x = 0; x < j; x++) { - if(srcp[x] != fg) { - if(bg == -1) bg = srcp[x]; - else if(bg != srcp[x]) return TRUE; - } else bits[y] |= 1 << x; - } - srcp += pitch; - } - } else if(pPixmap->drawable.bitsPerPixel == 24) { - CARD32 val; - unsigned char *srcp = pPixmap->devPrivate.ptr; - fg = *((CARD32*)srcp) & 0x00FFFFFF; - pitch = pPixmap->devKind; - j *= 3; - for(y = 0; y < i; y++) { - bits[y] = 0; - for(x = 0; x < j; x+=3) { - val = *((CARD32*)(srcp+x)) & 0x00FFFFFF; - if(val != fg) { - if(bg == -1) bg = val; - else if(bg != val) - return TRUE; - } else bits[y] |= 1 << (x/3); - } - srcp += pitch; - } - } else if(pPixmap->drawable.bitsPerPixel == 32) { - IntPtr = (CARD32*)pPixmap->devPrivate.ptr; - fg = IntPtr[0]; - for(y = 0; y < i; y++) { - bits[y] = 0; - for(x = 0; x < j; x++) { - if(IntPtr[x] != fg) { - if(bg == -1) bg = IntPtr[x]; - else if(bg != IntPtr[x]) return TRUE; - } else bits[y] |= 1 << x; - } - IntPtr += pitch; - } - } else return TRUE; - - pPriv->fg = fg; - if(bg == -1) pPriv->bg = fg; - else pPriv->bg = bg; - - if(h < 8) { - switch(h) { - case 1: bits[1] = bits[0]; - case 2: bits[2] = bits[0]; bits[3] = bits[1]; - case 4: bits[4] = bits[0]; bits[5] = bits[1]; - bits[6] = bits[2]; bits[7] = bits[3]; - break; - } - } - - pPriv->pattern0 = - bits[0] | (bits[1]<<8) | (bits[2]<<16) | (bits[3]<<24); - pPriv->pattern1 = - bits[4] | (bits[5]<<8) | (bits[6]<<16) | (bits[7]<<24); - - if(w < 8) { - switch(w) { - case 1: pPriv->pattern0 |= (pPriv->pattern0 << 1); - pPriv->pattern1 |= (pPriv->pattern1 << 1); - case 2: pPriv->pattern0 |= (pPriv->pattern0 << 2); - pPriv->pattern1 |= (pPriv->pattern1 << 2); - case 4: pPriv->pattern0 |= (pPriv->pattern0 << 4); - pPriv->pattern1 |= (pPriv->pattern1 << 4); - } - } - pPriv->flags |= REDUCIBLE_TO_2_COLOR; - - if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { - pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); - pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); - } - - } - - return TRUE; -} - - -void XAATileCache( - ScrnInfoPtr pScrn, - XAACacheInfoPtr pCache, - int w, int h -) { - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - - (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, ~0, -1); - - while((w << 1) <= pCache->w) { - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, - pCache->x + w, pCache->y, w, h); - w <<= 1; - } - if(w != pCache->w) { - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, - pCache->x + w, pCache->y, pCache->w - w, h); - w = pCache->w; - } - - while((h << 1) <= pCache->h) { - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, - pCache->x, pCache->y + h, w, h); - h <<= 1; - } - if(h != pCache->h) { - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, - pCache->x, pCache->y + h, w, pCache->h - h); - } - SET_SYNC_FLAG(infoRec); -} - -XAACacheInfoPtr -XAACacheTile(ScrnInfoPtr pScrn, PixmapPtr pPix) -{ - int w = pPix->drawable.width; - int h = pPix->drawable.height; - int size = max(w, h); - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache, cacheRoot = NULL; - int i, max = 0; - int *current; - - if(size <= 128) { - if(pCachePriv->Info128) { - cacheRoot = pCachePriv->Info128; - max = pCachePriv->Num128x128; - current = &pCachePriv->Current128; - } else { - cacheRoot = pCachePriv->InfoPartial; - max = pCachePriv->NumPartial; - current = &pCachePriv->CurrentPartial; - } - } else if(size <= 256) { - cacheRoot = pCachePriv->Info256; - max = pCachePriv->Num256x256; - current = &pCachePriv->Current256; - } else if(size <= 512) { - cacheRoot = pCachePriv->Info512; - max = pCachePriv->Num512x512; - current = &pCachePriv->Current512; - } else { /* something's wrong */ - ErrorF("Something's wrong in XAACacheTile()\n"); - return pCachePriv->Info128; - } - - pCache = cacheRoot; - - /* lets look for it */ - for(i = 0; i < max; i++, pCache++) { - if(pCache->serialNumber == pPix->drawable.serialNumber) { - pCache->trans_color = -1; - return pCache; - } - } - - pCache = &cacheRoot[(*current)++]; - if(*current >= max) *current = 0; - - pCache->serialNumber = pPix->drawable.serialNumber; - pCache->trans_color = pCache->bg = pCache->fg = -1; - pCache->orig_w = w; pCache->orig_h = h; - (*infoRec->WritePixmapToCache)( - pScrn, pCache->x, pCache->y, w, h, pPix->devPrivate.ptr, - pPix->devKind, pPix->drawable.bitsPerPixel, pPix->drawable.depth); - if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && - ((w != pCache->w) || (h != pCache->h))) - XAATileCache(pScrn, pCache, w, h); - - return pCache; -} - -XAACacheInfoPtr -XAACacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) -{ - int w = pPix->drawable.width; - int h = pPix->drawable.height; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache, cacheRoot = NULL; - int i, max = 0, funcNo, pad, dwords, bpp = pScrn->bitsPerPixel; - int *current; - StippleScanlineProcPtr StippleFunc; - unsigned char *data, *srcPtr, *dstPtr; - - if((h <= 128) && (w <= 128 * bpp)) { - if(pCachePriv->Info128) { - cacheRoot = pCachePriv->Info128; - max = pCachePriv->Num128x128; - current = &pCachePriv->Current128; - } else { - cacheRoot = pCachePriv->InfoPartial; - max = pCachePriv->NumPartial; - current = &pCachePriv->CurrentPartial; - } - } else if((h <= 256) && (w <= 256 * bpp)){ - cacheRoot = pCachePriv->Info256; - max = pCachePriv->Num256x256; - current = &pCachePriv->Current256; - } else if((h <= 512) && (w <= 526 * bpp)){ - cacheRoot = pCachePriv->Info512; - max = pCachePriv->Num512x512; - current = &pCachePriv->Current512; - } else { /* something's wrong */ - ErrorF("Something's wrong in XAACacheMonoStipple()\n"); - return pCachePriv->Info128; - } - - pCache = cacheRoot; - - /* lets look for it */ - for(i = 0; i < max; i++, pCache++) { - if((pCache->serialNumber == pPix->drawable.serialNumber) && - (pCache->fg == -1) && (pCache->bg == -1)) { - pCache->trans_color = -1; - return pCache; - } - } - - pCache = &cacheRoot[(*current)++]; - if(*current >= max) *current = 0; - - pCache->serialNumber = pPix->drawable.serialNumber; - pCache->trans_color = pCache->bg = pCache->fg = -1; - pCache->orig_w = w; pCache->orig_h = h; - - if(w <= 32) { - if(w & (w - 1)) funcNo = 1; - else funcNo = 0; - } else funcNo = 2; - - pad = BitmapBytePad(pCache->w * bpp); - dwords = bytes_to_int32(pad); - dstPtr = data = (unsigned char*)xalloc(pad * pCache->h); - srcPtr = (unsigned char*)pPix->devPrivate.ptr; - - if(infoRec->ScreenToScreenColorExpandFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) - StippleFunc = XAAStippleScanlineFuncMSBFirst[funcNo]; - else - StippleFunc = XAAStippleScanlineFuncLSBFirst[funcNo]; - - /* don't bother generating more than we'll ever use */ - max = ((pScrn->displayWidth + w - 1) + 31) >> 5; - if(dwords > max) - dwords = max; - - for(i = 0; i < h; i++) { - (*StippleFunc)((CARD32*)dstPtr, (CARD32*)srcPtr, 0, w, dwords); - srcPtr += pPix->devKind; - dstPtr += pad; - } - - while((h<<1) <= pCache->h) { - memcpy(data + (pad * h), data, pad * h); - h <<= 1; - } - - if(h < pCache->h) - memcpy(data + (pad * h), data, pad * (pCache->h - h)); - - (*infoRec->WritePixmapToCache)( - pScrn, pCache->x, pCache->y, pCache->w, pCache->h, data, - pad, bpp, pScrn->depth); - - xfree(data); - - return pCache; -} - -XAACacheInfoPtr -XAACachePlanarMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) -{ - int w = pPix->drawable.width; - int h = pPix->drawable.height; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache, cacheRoot = NULL; - int i, max = 0; - int *current; - - if((h <= 128) && (w <= 128)) { - if(pCachePriv->Info128) { - cacheRoot = pCachePriv->Info128; - max = pCachePriv->Num128x128; - current = &pCachePriv->Current128; - } else { - cacheRoot = pCachePriv->InfoPartial; - max = pCachePriv->NumPartial; - current = &pCachePriv->CurrentPartial; - } - } else if((h <= 256) && (w <= 256)){ - cacheRoot = pCachePriv->Info256; - max = pCachePriv->Num256x256; - current = &pCachePriv->Current256; - } else if((h <= 512) && (w <= 526)){ - cacheRoot = pCachePriv->Info512; - max = pCachePriv->Num512x512; - current = &pCachePriv->Current512; - } else { /* something's wrong */ - ErrorF("Something's wrong in XAACachePlanarMonoStipple()\n"); - return pCachePriv->Info128; - } - - pCache = cacheRoot; - - /* lets look for it */ - for(i = 0; i < max; i++, pCache++) { - if((pCache->serialNumber == pPix->drawable.serialNumber) && - (pCache->fg == -1) && (pCache->bg == -1)) { - pCache->trans_color = -1; - return pCache; - } - } - - pCache = &cacheRoot[(*current)++]; - if(*current >= max) *current = 0; - - pCache->serialNumber = pPix->drawable.serialNumber; - pCache->trans_color = pCache->bg = pCache->fg = -1; - pCache->orig_w = w; pCache->orig_h = h; - - /* Plane 0 holds the stipple. Plane 1 holds the inverted stipple */ - (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, - pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr, - pPix->devKind, 1, 2); - if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_MONO_DATA) && - ((w != pCache->w) || (h != pCache->h))) - XAATileCache(pScrn, pCache, w, h); - - return pCache; -} - -XAACachePlanarMonoStippleProc -XAAGetCachePlanarMonoStipple(void) -{ - return XAACachePlanarMonoStipple; -} - -XAACacheInfoPtr -XAACacheStipple(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) -{ - int w = pPix->drawable.width; - int h = pPix->drawable.height; - int size = max(w, h); - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache, cacheRoot = NULL; - int i, max = 0; - int *current; - - if(size <= 128) { - if(pCachePriv->Info128) { - cacheRoot = pCachePriv->Info128; - max = pCachePriv->Num128x128; - current = &pCachePriv->Current128; - } else { - cacheRoot = pCachePriv->InfoPartial; - max = pCachePriv->NumPartial; - current = &pCachePriv->CurrentPartial; - } - } else if(size <= 256) { - cacheRoot = pCachePriv->Info256; - max = pCachePriv->Num256x256; - current = &pCachePriv->Current256; - } else if(size <= 512) { - cacheRoot = pCachePriv->Info512; - max = pCachePriv->Num512x512; - current = &pCachePriv->Current512; - } else { /* something's wrong */ - ErrorF("Something's wrong in XAACacheStipple()\n"); - return pCachePriv->Info128; - } - - pCache = cacheRoot; - /* lets look for it */ - if(bg == -1) - for(i = 0; i < max; i++, pCache++) { - if((pCache->serialNumber == pPix->drawable.serialNumber) && - (fg == pCache->fg) && (pCache->fg != pCache->bg)) { - pCache->trans_color = pCache->bg; - return pCache; - } - } - else - for(i = 0; i < max; i++, pCache++) { - if((pCache->serialNumber == pPix->drawable.serialNumber) && - (fg == pCache->fg) && (bg == pCache->bg)) { - pCache->trans_color = -1; - return pCache; - } - } - - pCache = &cacheRoot[(*current)++]; - if(*current >= max) *current = 0; - - pCache->serialNumber = pPix->drawable.serialNumber; - pCache->fg = fg; - if(bg == -1) - pCache->trans_color = bg = fg ^ 1; - else - pCache->trans_color = -1; - pCache->bg = bg; - - pCache->orig_w = w; pCache->orig_h = h; - (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, - pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr, - pPix->devKind, fg, bg); - if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && - ((w != pCache->w) || (h != pCache->h))) - XAATileCache(pScrn, pCache, w, h); - - return pCache; -} - - - -XAACacheInfoPtr -XAACacheMono8x8Pattern(ScrnInfoPtr pScrn, int pat0, int pat1) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache = pCachePriv->InfoMono; - int i; - - for(i = 0; i < pCachePriv->NumMono; i++, pCache++) { - if(pCache->serialNumber && - (pCache->pat0 == pat0) && (pCache->pat1 == pat1)) - return pCache; - } - - /* OK, let's cache it */ - pCache = &pCachePriv->InfoMono[pCachePriv->CurrentMono++]; - if(pCachePriv->CurrentMono >= pCachePriv->NumMono) - pCachePriv->CurrentMono = 0; - - pCache->serialNumber = 1; /* we don't care since we do lookups by pattern */ - pCache->pat0 = pat0; - pCache->pat1 = pat1; - - (*infoRec->WriteMono8x8PatternToCache)(pScrn, pCache); - - return pCache; -} - - - -XAACacheInfoPtr -XAACacheColor8x8Pattern(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache = pCachePriv->InfoColor; - XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); - int i; - - if(!(pixPriv->flags & REDUCIBLE_TO_2_COLOR)) { - for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { - if(pCache->serialNumber == pPix->drawable.serialNumber) { - pCache->trans_color = -1; - return pCache; - } - } - pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; - if(pCachePriv->CurrentColor >= pCachePriv->NumColor) - pCachePriv->CurrentColor = 0; - - pCache->serialNumber = pPix->drawable.serialNumber; - pCache->trans_color = pCache->fg = pCache->bg = -1; - } else { - int pat0 = pixPriv->pattern0; - int pat1 = pixPriv->pattern1; - - if(fg == -1) { /* it's a tile */ - fg = pixPriv->fg; bg = pixPriv->bg; - } - - if(bg == -1) { /* stipple */ - for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { - if(pCache->serialNumber && - (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && - (pCache->fg == fg) && (pCache->bg != fg)) { - pCache->trans_color = pCache->bg; - return pCache; - } - } - } else { /* opaque stipple */ - for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { - if(pCache->serialNumber && - (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && - (pCache->fg == fg) && (pCache->bg == bg)) { - pCache->trans_color = -1; - return pCache; - } - } - } - pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; - if(pCachePriv->CurrentColor >= pCachePriv->NumColor) - pCachePriv->CurrentColor = 0; - - if(bg == -1) - pCache->trans_color = bg = fg ^ 1; - else - pCache->trans_color = -1; - - pCache->pat0 = pat0; pCache->pat1 = pat1; - pCache->fg = fg; pCache->bg = bg; - pCache->serialNumber = 1; - } - - (*infoRec->WriteColor8x8PatternToCache)(pScrn, pPix, pCache); - - return pCache; -} - - -void -XAAWriteBitmapToCache( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int fg, int bg -) { - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - - (*infoRec->WriteBitmap)(pScrn, x, y, w, h, src, srcwidth, - 0, fg, bg, GXcopy, ~0); -} - -void -XAAWriteBitmapToCacheLinear( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int fg, int bg -){ - ScreenPtr pScreen = pScrn->pScreen; - PixmapPtr pScreenPix, pDstPix; - XID gcvals[2]; - GCPtr pGC; - - pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); - - pDstPix = GetScratchPixmapHeader(pScreen, pScreenPix->drawable.width, - y + h, pScreenPix->drawable.depth, - pScreenPix->drawable.bitsPerPixel, - pScreenPix->devKind, - pScreenPix->devPrivate.ptr); - - pGC = GetScratchGC(pScreenPix->drawable.depth, pScreen); - gcvals[0] = fg; - gcvals[1] = bg; - DoChangeGC(pGC, GCForeground | GCBackground, gcvals, 0); - ValidateGC((DrawablePtr)pDstPix, pGC); - - /* We've unwrapped already so these ops miss a sync */ - SYNC_CHECK(pScrn); - - (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, 1, x, y, w, h, 0, - XYBitmap, (pointer)src); - - FreeScratchGC(pGC); - FreeScratchPixmapHeader(pDstPix); -} - - -void -XAAWritePixmapToCache( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int bpp, int depth -) { - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - - (*infoRec->WritePixmap)(pScrn, x, y, w, h, src, srcwidth, - GXcopy, ~0, -1, bpp, depth); -} - - - -void -XAAWritePixmapToCacheLinear( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int bpp, int depth -){ - ScreenPtr pScreen = pScrn->pScreen; - PixmapPtr pScreenPix, pDstPix; - GCPtr pGC; - - pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); - - pDstPix = GetScratchPixmapHeader(pScreen, x + w, y + h, - depth, bpp, pScreenPix->devKind, - pScreenPix->devPrivate.ptr); - - pGC = GetScratchGC(depth, pScreen); - ValidateGC((DrawablePtr)pDstPix, pGC); - - /* We've unwrapped already so these ops miss a sync */ - SYNC_CHECK(pScrn); - - if(bpp == BitsPerPixel(depth)) - (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, depth, x, y, w, - h, 0, ZPixmap, (pointer)src); - else { - PixmapPtr pSrcPix; - - pSrcPix = GetScratchPixmapHeader(pScreen, w, h, depth, bpp, - srcwidth, (pointer)src); - - (*pGC->ops->CopyArea)((DrawablePtr)pSrcPix, (DrawablePtr)pDstPix, - pGC, 0, 0, w, h, x, y); - - FreeScratchPixmapHeader(pSrcPix); - } - - FreeScratchGC(pGC); - FreeScratchPixmapHeader(pDstPix); -} - - -void -XAAWriteMono8x8PatternToCache( - ScrnInfoPtr pScrn, - XAACacheInfoPtr pCache -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - unsigned char *data; - int pad, Bpp = (pScrn->bitsPerPixel >> 3); - - pCache->offsets = pCachePriv->MonoOffsets; - - pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); - - data = (unsigned char*)xalloc(pad * pCache->h); - if(!data) return; - - if(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { - CARD32* ptr = (CARD32*)data; - ptr[0] = pCache->pat0; ptr[1] = pCache->pat1; - } else { - CARD32 *ptr; - DDXPointPtr pPoint = pCache->offsets; - int patx, paty, i; - - for(i = 0; i < 64; i++, pPoint++) { - patx = pCache->pat0; paty = pCache->pat1; - XAARotateMonoPattern(&patx, &paty, i & 0x07, i >> 3, - (infoRec->Mono8x8PatternFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST)); - ptr = (CARD32*)(data + (pad * pPoint->y) + (Bpp * pPoint->x)); - ptr[0] = patx; ptr[1] = paty; - } - } - - (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y, - pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth); - - xfree(data); -} - -void -XAAWriteColor8x8PatternToCache( - ScrnInfoPtr pScrn, - PixmapPtr pPix, - XAACacheInfoPtr pCache -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - int pad, i, w, h, nw, nh, Bpp; - unsigned char *data, *srcPtr, *dstPtr; - - pCache->offsets = pCachePriv->ColorOffsets; - - if(pixPriv->flags & REDUCIBLE_TO_2_COLOR) { - CARD32* ptr; - pad = BitmapBytePad(pCache->w); - data = (unsigned char*)xalloc(pad * pCache->h); - if(!data) return; - - if(infoRec->Color8x8PatternFillFlags & - HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { - ptr = (CARD32*)data; - ptr[0] = pCache->pat0; ptr[1] = pCache->pat1; - } else { - int patx, paty; - - ptr = (CARD32*)data; - ptr[0] = ptr[2] = pCache->pat0; ptr[1] = ptr[3] = pCache->pat1; - for(i = 1; i < 8; i++) { - patx = pCache->pat0; paty = pCache->pat1; - XAARotateMonoPattern(&patx, &paty, i, 0, - (infoRec->Mono8x8PatternFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST)); - ptr = (CARD32*)(data + (pad * i)); - ptr[0] = ptr[2] = patx; ptr[1] = ptr[3] = paty; - } - } - - (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, - pCache->w, pCache->h, data, pad, pCache->fg, pCache->bg); - - xfree(data); - return; - } - - Bpp = pScrn->bitsPerPixel >> 3; - h = min(8,pPix->drawable.height); - w = min(8,pPix->drawable.width); - pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); - - data = (unsigned char*)xalloc(pad * pCache->h); - if(!data) return; - - /* Write and expand horizontally. */ - for (i = h, dstPtr = data, srcPtr = pPix->devPrivate.ptr; i--; - srcPtr += pPix->devKind, dstPtr += pScrn->bitsPerPixel) { - nw = w; - memcpy(dstPtr, srcPtr, w * Bpp); - while (nw != 8) { - memcpy(dstPtr + (nw * Bpp), dstPtr, nw * Bpp); - nw <<= 1; - } - } - nh = h; - /* Expand vertically. */ - while (nh != 8) { - memcpy(data + (nh*pScrn->bitsPerPixel), data, nh*pScrn->bitsPerPixel); - nh <<= 1; - } - - if(!(infoRec->Color8x8PatternFillFlags & - HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){ - int j; - unsigned char *ptr = data + (128 * Bpp); - - memcpy(data + (64 * Bpp), data, 64 * Bpp); - for(i = 1; i < 8; i++, ptr += (128 * Bpp)) { - for(j = 0; j < 8; j++) { - memcpy(ptr + (j * 8) * Bpp, data + (j * 8 + i) * Bpp, - (8 - i) * Bpp); - memcpy(ptr + (j * 8 + 8 - i) * Bpp, data + j * 8 * Bpp, i*Bpp); - } - memcpy(ptr + (64 * Bpp), ptr, 64 * Bpp); - } - } - - (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y, - pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth); - - xfree(data); -} - - - -int -XAAStippledFillChooser(GCPtr pGC) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - PixmapPtr pPixmap = pGC->stipple; - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); - - if(!(pPriv->flags & REDUCIBILITY_CHECKED) && - (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { - XAACheckStippleReducibility(pPixmap); - } - - - if(pPriv->flags & REDUCIBLE_TO_8x8) { - if(infoRec->CanDoMono8x8 && - !(infoRec->FillMono8x8PatternSpansFlags & NO_TRANSPARENCY) && - ((pGC->alu == GXcopy) || !(infoRec->FillMono8x8PatternSpansFlags & - TRANSPARENCY_GXCOPY_ONLY)) && - CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_FG(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { - - return DO_MONO_8x8; - } - - if(infoRec->CanDoColor8x8 && - !(infoRec->FillColor8x8PatternSpansFlags & NO_TRANSPARENCY) && - ((pGC->alu == GXcopy) || !(infoRec->FillColor8x8PatternSpansFlags & - TRANSPARENCY_GXCOPY_ONLY)) && - CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { - - return DO_COLOR_8x8; - } - } - - if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && - (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && - (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / - infoRec->CacheColorExpandDensity) && - !(infoRec->FillCacheExpandSpansFlags & NO_TRANSPARENCY) && - ((pGC->alu == GXcopy) || !(infoRec->FillCacheExpandSpansFlags & - TRANSPARENCY_GXCOPY_ONLY)) && - CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_FG(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) { - - return DO_CACHE_EXPAND; - } - - - if(infoRec->UsingPixmapCache && - !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && - infoRec->FillCacheBltSpans && - (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && - (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && - !(infoRec->FillCacheBltSpansFlags & NO_TRANSPARENCY) && - ((pGC->alu == GXcopy) || !(infoRec->FillCacheBltSpansFlags & - TRANSPARENCY_GXCOPY_ONLY)) && - CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { - - return DO_CACHE_BLT; - } - - if(infoRec->FillColorExpandSpans && - !(infoRec->FillColorExpandSpansFlags & NO_TRANSPARENCY) && - ((pGC->alu == GXcopy) || !(infoRec->FillColorExpandSpansFlags & - TRANSPARENCY_GXCOPY_ONLY)) && - CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_FG(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) { - - return DO_COLOR_EXPAND; - } - - return 0; -} - - -int -XAAOpaqueStippledFillChooser(GCPtr pGC) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - PixmapPtr pPixmap = pGC->stipple; - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); - - if(XAA_DEPTH_BUG(pGC)) - return 0; - - if(!(pPriv->flags & REDUCIBILITY_CHECKED) && - (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { - XAACheckStippleReducibility(pPixmap); - } - - if(pPriv->flags & REDUCIBLE_TO_8x8) { - if(infoRec->CanDoMono8x8 && - !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && - CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_COLORS(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { - - return DO_MONO_8x8; - } - - if(infoRec->CanDoColor8x8 && - CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { - - return DO_COLOR_8x8; - } - } - - if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && - (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && - (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / - infoRec->CacheColorExpandDensity) && - !(infoRec->FillCacheExpandSpansFlags & TRANSPARENCY_ONLY) && - CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_COLORS(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) { - - return DO_CACHE_EXPAND; - } - - if(infoRec->UsingPixmapCache && - !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && - infoRec->FillCacheBltSpans && - (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && - (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && - CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { - - return DO_CACHE_BLT; - } - - if(infoRec->FillColorExpandSpans && - !(infoRec->FillColorExpandSpansFlags & TRANSPARENCY_ONLY) && - CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_COLORS(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) { - - return DO_COLOR_EXPAND; - } - - return 0; -} - - - -int -XAATiledFillChooser(GCPtr pGC) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - PixmapPtr pPixmap = pGC->tile.pixmap; - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); - - if(IS_OFFSCREEN_PIXMAP(pPixmap) && infoRec->FillCacheBltSpans && - CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { - - return DO_PIXMAP_COPY; - } - - if(!(pPriv->flags & REDUCIBILITY_CHECKED) && - (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { - XAACheckTileReducibility(pPixmap,infoRec->CanDoMono8x8); - } - - if(pPriv->flags & REDUCIBLE_TO_8x8) { - if((pPriv->flags & REDUCIBLE_TO_2_COLOR) && infoRec->CanDoMono8x8 && - !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && - CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && - (!(infoRec->FillMono8x8PatternSpansFlags & RGB_EQUAL) || - (CHECK_RGB_EQUAL(pPriv->fg) && CHECK_RGB_EQUAL(pPriv->bg))) && - CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { - - return DO_MONO_8x8; - } - - if(infoRec->CanDoColor8x8 && - CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { - - return DO_COLOR_8x8; - } - } - - if(infoRec->UsingPixmapCache && infoRec->FillCacheBltSpans && - (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && - (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && - CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { - - return DO_CACHE_BLT; - } - - if(infoRec->FillImageWriteRects && - CHECK_NO_GXCOPY(pGC,infoRec->FillImageWriteRectsFlags) && - CHECK_ROP(pGC,infoRec->FillImageWriteRectsFlags) && - CHECK_ROPSRC(pGC,infoRec->FillImageWriteRectsFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillImageWriteRectsFlags)) { - - return DO_IMAGE_WRITE; - } - - return 0; -} - - -static int RotateMasksX[8] = { - 0xFFFFFFFF, 0x7F7F7F7F, 0x3F3F3F3F, 0x1F1F1F1F, - 0x0F0F0F0F, 0x07070707, 0x03030303, 0x01010101 -}; - -static int RotateMasksY[4] = { - 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF -}; - -void -XAARotateMonoPattern( - int *pat0, int *pat1, - int xorg, int yorg, - Bool msbfirst -){ - int tmp, mask; - - if(xorg) { - if(msbfirst) xorg = 8 - xorg; - mask = RotateMasksX[xorg]; - *pat0 = ((*pat0 >> xorg) & mask) | ((*pat0 << (8 - xorg)) & ~mask); - *pat1 = ((*pat1 >> xorg) & mask) | ((*pat1 << (8 - xorg)) & ~mask); - } - if(yorg >= 4) { - tmp = *pat0; *pat0 = *pat1; *pat1 = tmp; - yorg -= 4; - } - if(yorg) { - mask = RotateMasksY[yorg]; - yorg <<= 3; - tmp = *pat0; - *pat0 = ((*pat0 >> yorg) & mask) | ((*pat1 << (32 - yorg)) & ~mask); - *pat1 = ((*pat1 >> yorg) & mask) | ((tmp << (32 - yorg)) & ~mask); - } -} - - - -void -XAAInvalidatePixmapCache(ScreenPtr pScreen) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - int i; - - if(!pCachePriv) return; - - for(i = 0; i < pCachePriv->Num512x512; i++) - (pCachePriv->Info512)[i].serialNumber = 0; - for(i = 0; i < pCachePriv->Num256x256; i++) - (pCachePriv->Info256)[i].serialNumber = 0; - for(i = 0; i < pCachePriv->Num128x128; i++) - (pCachePriv->Info128)[i].serialNumber = 0; - for(i = 0; i < pCachePriv->NumPartial; i++) - (pCachePriv->InfoPartial)[i].serialNumber = 0; - for(i = 0; i < pCachePriv->NumMono; i++) - (pCachePriv->InfoMono)[i].serialNumber = 0; - for(i = 0; i < pCachePriv->NumColor; i++) - (pCachePriv->InfoColor)[i].serialNumber = 0; -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "gc.h" +#include "mi.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "regionstr.h" +#include "servermd.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaacexp.h" +#include "xaalocal.h" +#include "xaawrap.h" + +#define MAX_COLOR 32 +#define MAX_MONO 32 +#define MAX_8 32 +#define MAX_128 32 +#define MAX_256 32 +#define MAX_512 16 + +static int CacheInitIndex = -1; +#define CACHEINIT(p) ((p)->privates[CacheInitIndex].val) + + +typedef struct _CacheLink { + int x; + int y; + int w; + int h; + struct _CacheLink *next; +} CacheLink, *CacheLinkPtr; + + +static void +TransferList(CacheLinkPtr list, XAACacheInfoPtr array, int num) +{ + while(num--) { + array->x = list->x; + array->y = list->y; + array->w = list->w; + array->h = list->h; + array->serialNumber = 0; + array->fg = array->bg = -1; + list = list->next; + array++; + } +} + + + +static CacheLinkPtr +Enlist(CacheLinkPtr link, int x, int y, int w, int h) +{ + CacheLinkPtr newLink; + + newLink = malloc(sizeof(CacheLink)); + newLink->next = link; + newLink->x = x; newLink->y = y; + newLink->w = w; newLink->h = h; + return newLink; +} + + + +static CacheLinkPtr +Delist(CacheLinkPtr link) { + CacheLinkPtr ret = NULL; + + if(link) { + ret = link->next; + free(link); + } + return ret; +} + + + +static void +FreeList(CacheLinkPtr link) { + CacheLinkPtr tmp; + + while(link) { + tmp = link; + link = link->next; + free(tmp); + } +} + + + +static CacheLinkPtr +QuadLinks(CacheLinkPtr big, CacheLinkPtr little) +{ + /* CAUTION: This doesn't free big */ + int w1, w2, h1, h2; + + while(big) { + w1 = big->w >> 1; + w2 = big->w - w1; + h1 = big->h >> 1; + h2 = big->h - h1; + + little = Enlist(little, big->x, big->y, w1, h1); + little = Enlist(little, big->x + w1, big->y, w2, h1); + little = Enlist(little, big->x, big->y + h1, w1, h2); + little = Enlist(little, big->x + w1, big->y + h1, w2, h2); + + big = big->next; + } + return little; +} + + +static void +SubdivideList(CacheLinkPtr *large, CacheLinkPtr *small) +{ + CacheLinkPtr big = *large; + CacheLinkPtr little = *small; + int size = big->w >> 1; + + little = Enlist(little, big->x, big->y, size, size); + little = Enlist(little, big->x + size, big->y, size, size); + little = Enlist(little, big->x, big->y + size, size, size); + little = Enlist(little, big->x + size, big->y + size, size, size); + *small = little; + big = Delist(big); + *large = big; +} + +static void +FreePixmapCachePrivate(XAAPixmapCachePrivatePtr pPriv) +{ + if(!pPriv) return; + + if(pPriv->Info512) + free(pPriv->Info512); + if(pPriv->Info256) + free(pPriv->Info256); + if(pPriv->Info128) + free(pPriv->Info128); + if(pPriv->InfoColor) + free(pPriv->InfoColor); + if(pPriv->InfoMono) + free(pPriv->InfoMono); + if(pPriv->InfoPartial) + free(pPriv->InfoPartial); + + free(pPriv); +} + +void +XAAClosePixmapCache(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + + if(infoRec->PixmapCachePrivate) + FreePixmapCachePrivate( + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate); + + infoRec->PixmapCachePrivate = NULL; +} + + + +static CacheLinkPtr +ThinOutPartials( + CacheLinkPtr ListPartial, + int *num, int *maxw, int *maxh +) { +/* This guy's job is to get at least 4 big slots out of a list of fragments */ + + CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; + int Num64, Num32, Num16, Num8, NumKeepers; + int w, h; + + List64 = List32 = List16 = List8 = ListKeepers = NULL; + Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; + w = h = 0; + + /* We sort partials by how large a square tile they can cache. + If a partial can't store a 64x64, 32x32, 16x16 or 8x8 tile, + we free it. */ + + pCur = ListPartial; + while(pCur) { + next = pCur->next; + if((pCur->w >= 64) && (pCur->h >= 64)) { + pCur->next = List64; List64 = pCur; + Num64++; + } else + if((pCur->w >= 32) && (pCur->h >= 32)) { + pCur->next = List32; List32 = pCur; + Num32++; + } else + if((pCur->w >= 16) && (pCur->h >= 16)) { + pCur->next = List16; List16 = pCur; + Num16++; + } else + if((pCur->w >= 8) && (pCur->h >= 8)) { + pCur->next = List8; List8 = pCur; + Num8++; + } else { + free(pCur); + } + + pCur = next; + } + + /* We save all the tiles from the largest bin that we can get + at least 4 of. If there are too few of a bigger slot, we + cut it in fourths to make smaller slots. */ + + if(Num64 >= 4) { + ListKeepers = List64; List64 = NULL; + NumKeepers = Num64; + goto GOT_EM; + } else if(Num64) { + List32 = QuadLinks(List64, List32); + Num32 += Num64 * 4; + Num64 = 0; + } + + if(Num32 >= 4) { + ListKeepers = List32; List32 = NULL; + NumKeepers = Num32; + goto GOT_EM; + } else if(Num32) { + List16 = QuadLinks(List32, List16); + Num16 += Num32 * 4; + Num32 = 0; + } + + if(Num16 >= 4) { + ListKeepers = List16; List16 = NULL; + NumKeepers = Num16; + goto GOT_EM; + } else if(Num16) { + List8 = QuadLinks(List16, List8); + Num8 += Num16 * 4; + Num16 = 0; + } + + if(Num8 >= 4) { + ListKeepers = List8; List8 = NULL; + NumKeepers = Num8; + goto GOT_EM; + } + +GOT_EM: + + /* Free the ones we aren't using */ + + if(List64) FreeList(List64); + if(List32) FreeList(List32); + if(List16) FreeList(List16); + if(List8) FreeList(List8); + + + /* Enlarge the slots if we can */ + + if(ListKeepers) { + CacheLinkPtr pLink = ListKeepers; + w = h = 128; + + while(pLink) { + if(pLink->w < w) w = pLink->w; + if(pLink->h < h) h = pLink->h; + pLink = pLink->next; + } + } + + *maxw = w; + *maxh = h; + *num = NumKeepers; + return ListKeepers; +} + +static void +ConvertColorToMono( + CacheLinkPtr *ColorList, + int ColorW, int ColorH, + CacheLinkPtr *MonoList, + int MonoW, int MonoH +){ + int x, y, w; + + x = (*ColorList)->x; y = (*ColorList)->y; + *ColorList = Delist(*ColorList); + + while(ColorH) { + ColorH -= MonoH; + for(w = 0; w <= (ColorW - MonoW); w += MonoW) + *MonoList = Enlist(*MonoList, x + w, y + ColorH, MonoW, MonoH); + } +} + +static void +ConvertAllPartialsTo8x8( + int *NumMono, int *NumColor, + CacheLinkPtr ListPartial, + CacheLinkPtr *ListMono, + CacheLinkPtr *ListColor, + XAAInfoRecPtr infoRec +){ +/* This guy extracts as many 8x8 slots as it can out of fragments */ + + int ColorH = infoRec->CacheHeightColor8x8Pattern; + int ColorW = infoRec->CacheWidthColor8x8Pattern; + int MonoH = infoRec->CacheHeightMono8x8Pattern; + int MonoW = infoRec->CacheWidthMono8x8Pattern; + int x, y, w, Height, Width; + Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); + Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); + CacheLinkPtr pLink = ListPartial; + CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; + + if(DoColor && DoMono) { + /* we assume color patterns take more space than color ones */ + if(MonoH > ColorH) ColorH = MonoH; + if(MonoW > ColorW) ColorW = MonoW; + } + + /* Break up the area into as many Color and Mono slots as we can */ + + while(pLink) { + Height = pLink->h; + Width = pLink->w; + x = pLink->x; + y = pLink->y; + + if(DoColor) { + while(Height >= ColorH) { + Height -= ColorH; + for(w = 0; w <= (Width - ColorW); w += ColorW) { + ColorList = Enlist( + ColorList, x + w, y + Height, ColorW, ColorH); + (*NumColor)++; + } + } + } + + if(DoMono && (Height >= MonoH)) { + while(Height >= MonoH) { + Height -= MonoH; + for(w = 0; w <= (Width - MonoW); w += MonoW) { + MonoList = Enlist( + MonoList, x + w, y + Height, MonoW, MonoH); + (*NumMono)++; + } + } + } + + pLink = pLink->next; + } + + + *ListMono = MonoList; + *ListColor = ColorList; + FreeList(ListPartial); +} + + +static CacheLinkPtr +ExtractOneThatFits(CacheLinkPtr *initList, int w, int h) +{ + CacheLinkPtr list = *initList; + CacheLinkPtr prev = NULL; + + while(list) { + if((list->w >= w) && (list->h >= h)) + break; + prev = list; + list = list->next; + } + + if(list) { + if(prev) + prev->next = list->next; + else + *initList = list->next; + + list->next = NULL; + } + + return list; +} + + +static CacheLinkPtr +ConvertSomePartialsTo8x8( + int *NumMono, int *NumColor, int *NumPartial, + CacheLinkPtr ListPartial, + CacheLinkPtr *ListMono, + CacheLinkPtr *ListColor, + int *maxw, int *maxh, + XAAInfoRecPtr infoRec +){ +/* This guy tries to get 4 of each type of 8x8 slot requested out of + a list of fragments all while trying to retain some big fragments + for the cache blits */ + + int ColorH = infoRec->CacheHeightColor8x8Pattern; + int ColorW = infoRec->CacheWidthColor8x8Pattern; + int MonoH = infoRec->CacheHeightMono8x8Pattern; + int MonoW = infoRec->CacheWidthMono8x8Pattern; + Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); + Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); + CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; + CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; + int Num64, Num32, Num16, Num8, NumKeepers; + int w, h, Width, Height; + int MonosPerColor = 1; + + if(DoColor && DoMono) { + /* we assume color patterns take more space than color ones */ + if(MonoH > ColorH) ColorH = MonoH; + if(MonoW > ColorW) ColorW = MonoW; + MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW); + } + + List64 = List32 = List16 = List8 = ListKeepers = MonoList = ColorList = NULL; + Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; + Width = Height = 0; + + /* We sort partials by how large a square tile they can cache. + We make 8x8 patterns from the leftovers if we can. */ + + pCur = ListPartial; + while(pCur) { + next = pCur->next; + if((pCur->w >= 64) && (pCur->h >= 64)) { + pCur->next = List64; List64 = pCur; + Num64++; + } else + if((pCur->w >= 32) && (pCur->h >= 32)) { + pCur->next = List32; List32 = pCur; + Num32++; + } else + if((pCur->w >= 16) && (pCur->h >= 16)) { + pCur->next = List16; List16 = pCur; + Num16++; + } else + if((pCur->w >= 8) && (pCur->h >= 8)) { + pCur->next = List8; List8 = pCur; + Num8++; + } else { + h = pCur->h; + if(DoColor && (pCur->w >= ColorW) && (h >= ColorH)) { + while(h >= ColorH) { + h -= ColorH; + for(w = 0; w <= (pCur->w - ColorW); w += ColorW) { + ColorList = Enlist( ColorList, + pCur->x + w, pCur->y + h, ColorW, ColorH); + (*NumColor)++; + } + } + } + if(DoMono && (pCur->w >= MonoW) && (h >= MonoH)) { + while(h >= MonoH) { + h -= MonoH; + for(w = 0; w <= (pCur->w - MonoW); w += MonoW) { + MonoList = Enlist( MonoList, + pCur->x + w, pCur->y + h, MonoW, MonoH); + (*NumMono)++; + } + } + } + free(pCur); + } + + pCur = next; + } + + /* Try to extract at least 4 of each type of 8x8 slot that we need */ + + if(DoColor) { + CacheLinkPtr theOne; + while(*NumColor < 4) { + theOne = NULL; + if(Num8) { + if((theOne = ExtractOneThatFits(&List8, ColorW, ColorH))) + Num8--; + } + if(Num16 && !theOne) { + if((theOne = ExtractOneThatFits(&List16, ColorW, ColorH))) + Num16--; + } + if(Num32 && !theOne) { + if((theOne = ExtractOneThatFits(&List32, ColorW, ColorH))) + Num32--; + } + if(Num64 && !theOne) { + if((theOne = ExtractOneThatFits(&List64, ColorW, ColorH))) + Num64--; + } + + if(!theOne) break; + + + ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, + &MonoList, &ColorList, infoRec); + + if(DoMono) { + while(*NumColor && (*NumMono < 4)) { + ConvertColorToMono(&ColorList, ColorW, ColorH, + &MonoList, MonoW, MonoH); + (*NumColor)--; *NumMono += MonosPerColor; + } + } + } + } + + if(DoMono) { + CacheLinkPtr theOne; + while(*NumMono < 4) { + theOne = NULL; + if(Num8) { + if((theOne = ExtractOneThatFits(&List8, MonoW, MonoH))) + Num8--; + } + if(Num16 && !theOne) { + if((theOne = ExtractOneThatFits(&List16, MonoW, MonoH))) + Num16--; + } + if(Num32 && !theOne) { + if((theOne = ExtractOneThatFits(&List32, MonoW, MonoH))) + Num32--; + } + if(Num64 && !theOne) { + if((theOne = ExtractOneThatFits(&List64, MonoW, MonoH))) + Num64--; + } + + if(!theOne) break; + + ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, + &MonoList, &ColorList, infoRec); + } + } + + /* We save all the tiles from the largest bin that we can get + at least 4 of. If there are too few of a bigger slot, we + cut it in fourths to make smaller slots. */ + + if(Num64 >= 4) { + ListKeepers = List64; List64 = NULL; + NumKeepers = Num64; + goto GOT_EM; + } else if(Num64) { + List32 = QuadLinks(List64, List32); + Num32 += Num64 * 4; + Num64 = 0; + } + + if(Num32 >= 4) { + ListKeepers = List32; List32 = NULL; + NumKeepers = Num32; + goto GOT_EM; + } else if(Num32) { + List16 = QuadLinks(List32, List16); + Num16 += Num32 * 4; + Num32 = 0; + } + + if(Num16 >= 4) { + ListKeepers = List16; List16 = NULL; + NumKeepers = Num16; + goto GOT_EM; + } else if(Num16) { + List8 = QuadLinks(List16, List8); + Num8 += Num16 * 4; + Num16 = 0; + } + + if(Num8 >= 4) { + ListKeepers = List8; List8 = NULL; + NumKeepers = Num8; + goto GOT_EM; + } + +GOT_EM: + + /* Free the ones we aren't using */ + + if(List64) + ConvertAllPartialsTo8x8(NumMono, NumColor, List64, + &MonoList, &ColorList, infoRec); + if(List32) + ConvertAllPartialsTo8x8(NumMono, NumColor, List32, + &MonoList, &ColorList, infoRec); + if(List16) + ConvertAllPartialsTo8x8(NumMono, NumColor, List16, + &MonoList, &ColorList, infoRec); + if(List8) + ConvertAllPartialsTo8x8(NumMono, NumColor, List8, + &MonoList, &ColorList, infoRec); + + + /* Enlarge the slots if we can */ + + if(ListKeepers) { + CacheLinkPtr pLink = ListKeepers; + Width = Height = 128; + + while(pLink) { + if(pLink->w < Width) Width = pLink->w; + if(pLink->h < Height) Height = pLink->h; + pLink = pLink->next; + } + } + + *ListMono = MonoList; + *ListColor = ColorList; + *maxw = Width; + *maxh = Height; + *NumPartial = NumKeepers; + return ListKeepers; +} + + +void +XAAInitPixmapCache( + ScreenPtr pScreen, + RegionPtr areas, + pointer data +) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XAAInfoRecPtr infoRec = (XAAInfoRecPtr)data; + XAAPixmapCachePrivatePtr pCachePriv; + BoxPtr pBox = REGION_RECTS(areas); + int nBox = REGION_NUM_RECTS(areas); + int Num512, Num256, Num128, NumPartial, NumColor, NumMono; + int Target512, Target256; + CacheLinkPtr List512, List256, List128, ListPartial, ListColor, ListMono; + int x, y, w, h, ntotal, granularity, width, height, i; + int MaxPartialWidth, MaxPartialHeight; + + infoRec->MaxCacheableTileWidth = 0; + infoRec->MaxCacheableTileHeight = 0; + infoRec->MaxCacheableStippleHeight = 0; + infoRec->MaxCacheableStippleWidth = 0; + infoRec->UsingPixmapCache = FALSE; + + + if(!nBox || !pBox || !(infoRec->Flags & PIXMAP_CACHE)) + return; + + /* Allocate a persistent per-screen init flag to control messages */ + if (CacheInitIndex < 0) + CacheInitIndex = xf86AllocateScrnInfoPrivateIndex(); + + /* free the old private data if it exists */ + if(infoRec->PixmapCachePrivate) { + FreePixmapCachePrivate( + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate); + infoRec->PixmapCachePrivate = NULL; + } + + Num512 = Num256 = Num128 = NumPartial = NumMono = NumColor = 0; + List512 = List256 = List128 = ListPartial = ListMono = ListColor = NULL; + granularity = infoRec->CachePixelGranularity; + if(granularity <= 1) granularity = 0; + + /* go through the boxes and break it into as many pieces as we can fit */ + + while(nBox--) { + x = pBox->x1; + if(granularity) { + int tmp = x % granularity; + if(tmp) x += (granularity - tmp); + } + width = pBox->x2 - x; + if(width <= 0) {pBox++; continue;} + + y = pBox->y1; + height = pBox->y2 - y; + + for(h = 0; h <= (height - 512); h += 512) { + for(w = 0; w <= (width - 512); w += 512) { + List512 = Enlist(List512, x + w, y + h, 512, 512); + Num512++; + } + for(; w <= (width - 256); w += 256) { + List256 = Enlist(List256, x + w, y + h, 256, 256); + List256 = Enlist(List256, x + w, y + h + 256, 256, 256); + Num256 += 2; + } + for(; w <= (width - 128); w += 128) { + List128 = Enlist(List128, x + w, y + h, 128, 128); + List128 = Enlist(List128, x + w, y + h + 128, 128, 128); + List128 = Enlist(List128, x + w, y + h + 256, 128, 128); + List128 = Enlist(List128, x + w, y + h + 384, 128, 128); + Num128 += 4; + } + if(w < width) { + int d = width - w; + ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 256, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 384, d, 128); + NumPartial += 4; + } + } + for(; h <= (height - 256); h += 256) { + for(w = 0; w <= (width - 256); w += 256) { + List256 = Enlist(List256, x + w, y + h, 256, 256); + Num256++; + } + for(; w <= (width - 128); w += 128) { + List128 = Enlist(List128, x + w, y + h, 128, 128); + List128 = Enlist(List128, x + w, y + h + 128, 128, 128); + Num128 += 2; + } + if(w < width) { + int d = width - w; + ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); + NumPartial += 2; + } + } + for(; h <= (height - 128); h += 128) { + for(w = 0; w <= (width - 128); w += 128) { + List128 = Enlist(List128, x + w, y + h, 128, 128); + Num128++; + } + if(w < width) { + ListPartial = Enlist( + ListPartial, x + w, y + h, width - w, 128); + NumPartial++; + } + } + if(h < height) { + int d = height - h; + for(w = 0; w <= (width - 128); w += 128) { + ListPartial = Enlist(ListPartial, x + w, y + h, 128, d); + NumPartial++; + } + if(w < width) { + ListPartial = Enlist(ListPartial, x + w, y + h, width - w, d); + NumPartial++; + } + } + pBox++; + } + + +/* + by this point we've carved the space into as many 512x512, 256x256 + and 128x128 blocks as we could fit. We will then break larger + blocks into smaller ones if we need to. The rules are as follows: + + 512x512 - + 1) Don't take up more than half the memory. + 2) Don't bother if you can't get at least four. + 3) Don't make more than MAX_512. + 4) Don't have any of there are no 256x256s. + + 256x256 - + 1) Don't take up more than a quarter of the memory enless there + aren't any 512x512s. Then we can take up to half. + 2) Don't bother if you can't get at least four. + 3) Don't make more than MAX_256. + + 128x128 - + 1) Don't make more than MAX_128. + + We don't bother with the partial blocks unless we can use them + for 8x8 pattern fills or we are short on larger blocks. + +*/ + + ntotal = Num128 + (Num256<<2) + (Num512<<4); + + Target512 = ntotal >> 5; + if(Target512 < 4) Target512 = 0; + if(!Target512) Target256 = ntotal >> 3; + else Target256 = ntotal >> 4; + if(Target256 < 4) Target256 = 0; + + if(Num512 && Num256 < 4) { + while(Num512 && Num256 < Target256) { + SubdivideList(&List512, &List256); + Num256 += 4; Num512--; + } + } + + if(!Num512) { /* no room */ + } else if((Num512 < 4) || (!Target512)) { + while(Num512) { + SubdivideList(&List512, &List256); + Num256 += 4; Num512--; + } + } else if((Num512 > MAX_512) || (Num512 > Target512)){ + while(Num512 > MAX_512) { + SubdivideList(&List512, &List256); + Num256 += 4; Num512--; + } + while(Num512 > Target512) { + if(Num256 < MAX_256) { + SubdivideList(&List512, &List256); + Num256 += 4; Num512--; + } else break; + } + } + + if(!Num256) { /* no room */ + } else if((Num256 < 4) || (!Target256)) { + while(Num256) { + SubdivideList(&List256, &List128); + Num128 += 4; Num256--; + } + } else if((Num256 > MAX_256) || (Num256 > Target256)) { + while(Num256 > MAX_256) { + SubdivideList(&List256, &List128); + Num128 += 4; Num256--; + } + while(Num256 > Target256) { + if(Num128 < MAX_128) { + SubdivideList(&List256, &List128); + Num128 += 4; Num256--; + } else break; + } + } + + if(Num128 && ((Num128 < 4) || (Num128 > MAX_128))) { + CacheLinkPtr next; + int max = (Num128 > MAX_128) ? MAX_128 : 0; + + /* + * Note: next is set in this way to work around a code generation + * bug in gcc 2.7.2.3. + */ + next = List128->next; + while(Num128 > max) { + List128->next = ListPartial; + ListPartial = List128; + if((List128 = next)) + next = List128->next; + NumPartial++; Num128--; + } + } + + MaxPartialHeight = MaxPartialWidth = 0; + + /* at this point we have as many 512x512 and 256x256 slots as we + want but may have an excess of 128x128 slots. We still need + to find out if we need 8x8 slots. We take these from the + partials if we have them. Otherwise, we break some 128x128's */ + + if(!(infoRec->PixmapCacheFlags & (CACHE_MONO_8x8 | CACHE_COLOR_8x8))) { + if(NumPartial) { + if(Num128) { /* don't bother with partials */ + FreeList(ListPartial); + NumPartial = 0; ListPartial = NULL; + } else { + /* We have no big slots. Weed out the unusable partials */ + ListPartial = ThinOutPartials(ListPartial, &NumPartial, + &MaxPartialWidth, &MaxPartialHeight); + } + } + } else { + int MonosPerColor = 1; + int ColorH = infoRec->CacheHeightColor8x8Pattern; + int ColorW = infoRec->CacheWidthColor8x8Pattern; + int MonoH = infoRec->CacheHeightMono8x8Pattern; + int MonoW = infoRec->CacheWidthMono8x8Pattern; + Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); + Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); + + if(DoColor) infoRec->CanDoColor8x8 = FALSE; + if(DoMono) infoRec->CanDoMono8x8 = FALSE; + + if(DoColor && DoMono) { + /* we assume color patterns take more space than color ones */ + if(MonoH > ColorH) ColorH = MonoH; + if(MonoW > ColorW) ColorW = MonoW; + MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW); + } + + if(Num128) { + if(NumPartial) { /* use all for 8x8 slots */ + ConvertAllPartialsTo8x8(&NumMono, &NumColor, + ListPartial, &ListMono, &ListColor, infoRec); + NumPartial = 0; ListPartial = NULL; + } + + /* Get some 8x8 slots from the 128 slots */ + while((Num128 > 4) && + ((NumMono < MAX_MONO) && (NumColor < MAX_COLOR))) { + CacheLinkPtr tmp = NULL; + + tmp = Enlist(tmp, List128->x, List128->y, + List128->w, List128->h); + List128 = Delist(List128); + Num128--; + + ConvertAllPartialsTo8x8(&NumMono, &NumColor, + tmp, &ListMono, &ListColor, infoRec); + } + } else if(NumPartial) { + /* We have share partials between 8x8 slots and tiles. */ + ListPartial = ConvertSomePartialsTo8x8(&NumMono, &NumColor, + &NumPartial, ListPartial, &ListMono, &ListColor, + &MaxPartialWidth, &MaxPartialHeight, infoRec); + } + + + if(DoMono && DoColor) { + if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { + int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; + + while(NumColor > max) { + ConvertColorToMono(&ListColor, ColorW, ColorH, + &ListMono, MonoW, MonoH); + NumColor--; NumMono += MonosPerColor; + } + } + + /* favor Mono slots over Color ones */ + while((NumColor > 4) && (NumMono < MAX_MONO)) { + ConvertColorToMono(&ListColor, ColorW, ColorH, + &ListMono, MonoW, MonoH); + NumColor--; NumMono += MonosPerColor; + } + } + + if(NumMono && ((NumMono > MAX_MONO) || (NumMono < 4))) { + int max = (NumMono > MAX_MONO) ? MAX_MONO : 0; + + while(NumMono > max) { + ListMono = Delist(ListMono); + NumMono--; + } + } + if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { + int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; + + while(NumColor > max) { + ListColor = Delist(ListColor); + NumColor--; + } + } + } + + + pCachePriv = calloc(1,sizeof(XAAPixmapCachePrivate)); + if(!pCachePriv) { + if(Num512) FreeList(List512); + if(Num256) FreeList(List256); + if(Num128) FreeList(List128); + if(NumPartial) FreeList(ListPartial); + if(NumColor) FreeList(ListColor); + if(NumMono) FreeList(ListMono); + return; + } + + infoRec->PixmapCachePrivate = (char*)pCachePriv; + + if(Num512) { + pCachePriv->Info512 = calloc(Num512,sizeof(XAACacheInfoRec)); + if(!pCachePriv->Info512) Num512 = 0; + if(Num512) TransferList(List512, pCachePriv->Info512, Num512); + FreeList(List512); + pCachePriv->Num512x512 = Num512; + } + if(Num256) { + pCachePriv->Info256 = calloc(Num256, sizeof(XAACacheInfoRec)); + if(!pCachePriv->Info256) Num256 = 0; + if(Num256) TransferList(List256, pCachePriv->Info256, Num256); + FreeList(List256); + pCachePriv->Num256x256 = Num256; + } + if(Num128) { + pCachePriv->Info128 = calloc(Num128, sizeof(XAACacheInfoRec)); + if(!pCachePriv->Info128) Num128 = 0; + if(Num128) TransferList(List128, pCachePriv->Info128, Num128); + FreeList(List128); + pCachePriv->Num128x128 = Num128; + } + + if(NumPartial) { + pCachePriv->InfoPartial = calloc(NumPartial, sizeof(XAACacheInfoRec)); + if(!pCachePriv->InfoPartial) NumPartial = 0; + if(NumPartial) + TransferList(ListPartial, pCachePriv->InfoPartial, NumPartial); + FreeList(ListPartial); + pCachePriv->NumPartial = NumPartial; + } + + if(NumColor) { + pCachePriv->InfoColor = calloc(NumColor, sizeof(XAACacheInfoRec)); + if(!pCachePriv->InfoColor) NumColor = 0; + if(NumColor) TransferList(ListColor, pCachePriv->InfoColor, NumColor); + FreeList(ListColor); + pCachePriv->NumColor = NumColor; + } + + if(NumMono) { + pCachePriv->InfoMono = calloc(NumMono, sizeof(XAACacheInfoRec)); + if(!pCachePriv->InfoMono) NumMono = 0; + if(NumMono) TransferList(ListMono, pCachePriv->InfoMono, NumMono); + FreeList(ListMono); + pCachePriv->NumMono = NumMono; + } + + + if(NumPartial) { + infoRec->MaxCacheableTileWidth = MaxPartialWidth; + infoRec->MaxCacheableTileHeight = MaxPartialHeight; + } + if(Num128) + infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 128; + if(Num256) + infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 256; + if(Num512) + infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 512; + + + infoRec->MaxCacheableStippleHeight = infoRec->MaxCacheableTileHeight; + infoRec->MaxCacheableStippleWidth = + infoRec->MaxCacheableTileWidth * pScrn->bitsPerPixel; + if(infoRec->ScreenToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) + infoRec->MaxCacheableStippleWidth /= 3; + + if(NumMono) { + if(!(infoRec->Mono8x8PatternFillFlags & + (HARDWARE_PATTERN_PROGRAMMED_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_BITS))) { + int numPerLine = + infoRec->CacheWidthMono8x8Pattern/infoRec->MonoPatternPitch; + + for(i = 0; i < 64; i++) { + pCachePriv->MonoOffsets[i].y = i/numPerLine; + pCachePriv->MonoOffsets[i].x = (i % numPerLine) * + infoRec->MonoPatternPitch; + } + } + infoRec->CanDoMono8x8 = TRUE; + } + if(NumColor) { + if(!(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + + for(i = 0; i < 64; i++) { + pCachePriv->ColorOffsets[i].y = i & 0x07; + pCachePriv->ColorOffsets[i].x = i & ~0x07; + } + } + infoRec->CanDoColor8x8 = TRUE; + } + + if(!CACHEINIT(pScrn)) { + xf86ErrorF("\tSetting up tile and stipple cache:\n"); + if(NumPartial) + xf86ErrorF("\t\t%i %ix%i slots\n", + NumPartial, MaxPartialWidth, MaxPartialHeight); + if(Num128) xf86ErrorF("\t\t%i 128x128 slots\n", Num128); + if(Num256) xf86ErrorF("\t\t%i 256x256 slots\n", Num256); + if(Num512) xf86ErrorF("\t\t%i 512x512 slots\n", Num512); + if(NumColor) xf86ErrorF("\t\t%i 8x8 color pattern slots\n", NumColor); + if(NumMono) xf86ErrorF("\t\t%i 8x8 color expansion slots\n", NumMono); + } + + if(!(NumPartial | Num128 | Num256 | Num512 | NumColor | NumMono)) { + if(!CACHEINIT(pScrn)) + xf86ErrorF("\t\tNot enough video memory for pixmap cache\n"); + } else infoRec->UsingPixmapCache = TRUE; + + CACHEINIT(pScrn) = 1; +} + +#if X_BYTE_ORDER == X_BIG_ENDIAN +static CARD32 StippleMasks[4] = { + 0x80808080, + 0xC0C0C0C0, + 0x00000000, + 0xF0F0F0F0 +}; +#else +static CARD32 StippleMasks[4] = { + 0x01010101, + 0x03030303, + 0x00000000, + 0x0F0F0F0F +}; +#endif + +Bool +XAACheckStippleReducibility(PixmapPtr pPixmap) +{ + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); + CARD32 *IntPtr = (CARD32*)pPixmap->devPrivate.ptr; + int w = pPixmap->drawable.width; + int h = pPixmap->drawable.height; + int i; + CARD32 bits[8]; + CARD32 mask = SHIFT_R(0xFFFFFFFF,24); + + pPriv->flags |= REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR; + pPriv->flags &= ~REDUCIBLE_TO_8x8; + + if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) + return FALSE; + + i = (h > 8) ? 8 : h; + + switch(w) { + case 32: + while(i--) { + bits[i] = IntPtr[i] & mask; + if( (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask, 8)), 8)) || + (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,16)),16)) || + (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,24)),24))) + return FALSE; + } + break; + case 16: + while(i--) { + bits[i] = IntPtr[i] & mask; + if(bits[i] != ((IntPtr[i] & SHIFT_R(SHIFT_L(mask,8),8)))) + return FALSE; + } + break; + default: + while(i--) + bits[i] = IntPtr[i] & mask; + break; + } + + switch(h) { + case 32: + if( (IntPtr[8] != IntPtr[16]) || (IntPtr[9] != IntPtr[17]) || + (IntPtr[10] != IntPtr[18]) || (IntPtr[11] != IntPtr[19]) || + (IntPtr[12] != IntPtr[20]) || (IntPtr[13] != IntPtr[21]) || + (IntPtr[14] != IntPtr[22]) || (IntPtr[15] != IntPtr[23]) || + (IntPtr[16] != IntPtr[24]) || (IntPtr[17] != IntPtr[25]) || + (IntPtr[18] != IntPtr[26]) || (IntPtr[19] != IntPtr[27]) || + (IntPtr[20] != IntPtr[28]) || (IntPtr[21] != IntPtr[29]) || + (IntPtr[22] != IntPtr[30]) || (IntPtr[23] != IntPtr[31])) + return FALSE; + /* fall through */ + case 16: + if( (IntPtr[0] != IntPtr[8]) || (IntPtr[1] != IntPtr[9]) || + (IntPtr[2] != IntPtr[10]) || (IntPtr[3] != IntPtr[11]) || + (IntPtr[4] != IntPtr[12]) || (IntPtr[5] != IntPtr[13]) || + (IntPtr[6] != IntPtr[14]) || (IntPtr[7] != IntPtr[15])) + return FALSE; + case 8: break; + case 1: bits[1] = bits[0]; + case 2: bits[2] = bits[0]; bits[3] = bits[1]; + case 4: bits[4] = bits[0]; bits[5] = bits[1]; + bits[6] = bits[2]; bits[7] = bits[3]; + break; + } + + pPriv->flags |= REDUCIBLE_TO_8x8; + + pPriv->pattern0 = bits[0] | SHIFT_L(bits[1],8) | SHIFT_L(bits[2],16) | SHIFT_L(bits[3],24); + pPriv->pattern1 = bits[4] | SHIFT_L(bits[5],8) | SHIFT_L(bits[6],16) | SHIFT_L(bits[7],24); + + if(w < 8) { + pPriv->pattern0 &= StippleMasks[w - 1]; + pPriv->pattern1 &= StippleMasks[w - 1]; + + switch(w) { + case 1: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,1); + pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,1); + case 2: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,2); + pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,2); + case 4: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,4); + pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,4); + } + } + + if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { + pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); + pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); + } + + + return TRUE; +} + + +Bool +XAACheckTileReducibility(PixmapPtr pPixmap, Bool checkMono) +{ + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + CARD32 *IntPtr; + int w = pPixmap->drawable.width; + int h = pPixmap->drawable.height; + int pitch = pPixmap->devKind >> 2; + int dwords, i, j; + + pPriv->flags |= REDUCIBILITY_CHECKED; + pPriv->flags &= ~(REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR); + + if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) + return FALSE; + + dwords = ((w * pPixmap->drawable.bitsPerPixel) + 31) >> 5; + i = (h > 8) ? 8 : h; + + + if(w > 8) { + IntPtr = (CARD32*)pPixmap->devPrivate.ptr; + switch(pPixmap->drawable.bitsPerPixel) { + case 8: + while(i--) { + for(j = 2; j < dwords; j++) + if(IntPtr[j] != IntPtr[j & 0x01]) + return FALSE; + IntPtr += pitch; + } + break; + case 16: + while(i--) { + for(j = 4; j < dwords; j++) + if(IntPtr[j] != IntPtr[j & 0x03]) + return FALSE; + IntPtr += pitch; + } + break; + case 24: + while(i--) { + for(j = 6; j < dwords; j++) + if(IntPtr[j] != IntPtr[j % 6]) + return FALSE; + IntPtr += pitch; + } + break; + case 32: + while(i--) { + for(j = 8; j < dwords; j++) + if(IntPtr[j] != IntPtr[j & 0x07]) + return FALSE; + IntPtr += pitch; + } + break; + default: return FALSE; + } + + } + + + if(h == 32) { + CARD32 *IntPtr2, *IntPtr3, *IntPtr4; + i = 8; + IntPtr = (CARD32*)pPixmap->devPrivate.ptr; + IntPtr2 = IntPtr + (pitch << 3); + IntPtr3 = IntPtr2 + (pitch << 3); + IntPtr4 = IntPtr3 + (pitch << 3); + while(i--) { + for(j = 0; j < dwords; j++) + if((IntPtr[j] != IntPtr2[j]) || (IntPtr[j] != IntPtr3[j]) || + (IntPtr[j] != IntPtr4[j])) + return FALSE; + IntPtr += pitch; + IntPtr2 += pitch; + IntPtr3 += pitch; + IntPtr4 += pitch; + } + } else if (h == 16) { + CARD32 *IntPtr2; + i = 8; + IntPtr = (CARD32*)pPixmap->devPrivate.ptr; + IntPtr2 = IntPtr + (pitch << 3); + while(i--) { + for(j = 0; j < dwords; j++) + if(IntPtr[j] != IntPtr2[j]) + return FALSE; + IntPtr += pitch; + IntPtr2 += pitch; + } + } + + pPriv->flags |= REDUCIBLE_TO_8x8; + + if(checkMono) { + XAAInfoRecPtr infoRec = + GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); + unsigned char bits[8]; + int fg, bg = -1, x, y; + + i = (h > 8) ? 8 : h; + j = (w > 8) ? 8 : w; + + if(pPixmap->drawable.bitsPerPixel == 8) { + unsigned char *srcp = pPixmap->devPrivate.ptr; + fg = srcp[0]; + pitch = pPixmap->devKind; + for(y = 0; y < i; y++) { + bits[y] = 0; + for(x = 0; x < j; x++) { + if(srcp[x] != fg) { + if(bg == -1) bg = srcp[x]; + else if(bg != srcp[x]) return TRUE; + } else bits[y] |= 1 << x; + } + srcp += pitch; + } + } else if(pPixmap->drawable.bitsPerPixel == 16) { + unsigned short *srcp = (unsigned short*)pPixmap->devPrivate.ptr; + fg = srcp[0]; + pitch = pPixmap->devKind >> 1; + for(y = 0; y < i; y++) { + bits[y] = 0; + for(x = 0; x < j; x++) { + if(srcp[x] != fg) { + if(bg == -1) bg = srcp[x]; + else if(bg != srcp[x]) return TRUE; + } else bits[y] |= 1 << x; + } + srcp += pitch; + } + } else if(pPixmap->drawable.bitsPerPixel == 24) { + CARD32 val; + unsigned char *srcp = pPixmap->devPrivate.ptr; + fg = *((CARD32*)srcp) & 0x00FFFFFF; + pitch = pPixmap->devKind; + j *= 3; + for(y = 0; y < i; y++) { + bits[y] = 0; + for(x = 0; x < j; x+=3) { + val = *((CARD32*)(srcp+x)) & 0x00FFFFFF; + if(val != fg) { + if(bg == -1) bg = val; + else if(bg != val) + return TRUE; + } else bits[y] |= 1 << (x/3); + } + srcp += pitch; + } + } else if(pPixmap->drawable.bitsPerPixel == 32) { + IntPtr = (CARD32*)pPixmap->devPrivate.ptr; + fg = IntPtr[0]; + for(y = 0; y < i; y++) { + bits[y] = 0; + for(x = 0; x < j; x++) { + if(IntPtr[x] != fg) { + if(bg == -1) bg = IntPtr[x]; + else if(bg != IntPtr[x]) return TRUE; + } else bits[y] |= 1 << x; + } + IntPtr += pitch; + } + } else return TRUE; + + pPriv->fg = fg; + if(bg == -1) pPriv->bg = fg; + else pPriv->bg = bg; + + if(h < 8) { + switch(h) { + case 1: bits[1] = bits[0]; + case 2: bits[2] = bits[0]; bits[3] = bits[1]; + case 4: bits[4] = bits[0]; bits[5] = bits[1]; + bits[6] = bits[2]; bits[7] = bits[3]; + break; + } + } + + pPriv->pattern0 = + bits[0] | (bits[1]<<8) | (bits[2]<<16) | (bits[3]<<24); + pPriv->pattern1 = + bits[4] | (bits[5]<<8) | (bits[6]<<16) | (bits[7]<<24); + + if(w < 8) { + switch(w) { + case 1: pPriv->pattern0 |= (pPriv->pattern0 << 1); + pPriv->pattern1 |= (pPriv->pattern1 << 1); + case 2: pPriv->pattern0 |= (pPriv->pattern0 << 2); + pPriv->pattern1 |= (pPriv->pattern1 << 2); + case 4: pPriv->pattern0 |= (pPriv->pattern0 << 4); + pPriv->pattern1 |= (pPriv->pattern1 << 4); + } + } + pPriv->flags |= REDUCIBLE_TO_2_COLOR; + + if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { + pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); + pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); + } + + } + + return TRUE; +} + + +void XAATileCache( + ScrnInfoPtr pScrn, + XAACacheInfoPtr pCache, + int w, int h +) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, ~0, -1); + + while((w << 1) <= pCache->w) { + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, + pCache->x + w, pCache->y, w, h); + w <<= 1; + } + if(w != pCache->w) { + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, + pCache->x + w, pCache->y, pCache->w - w, h); + w = pCache->w; + } + + while((h << 1) <= pCache->h) { + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, + pCache->x, pCache->y + h, w, h); + h <<= 1; + } + if(h != pCache->h) { + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, + pCache->x, pCache->y + h, w, pCache->h - h); + } + SET_SYNC_FLAG(infoRec); +} + +XAACacheInfoPtr +XAACacheTile(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + int size = max(w, h); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0; + int *current; + + if(size <= 128) { + if(pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } else if(size <= 256) { + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } else if(size <= 512) { + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } else { /* something's wrong */ + ErrorF("Something's wrong in XAACacheTile()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + + /* lets look for it */ + for(i = 0; i < max; i++, pCache++) { + if(pCache->serialNumber == pPix->drawable.serialNumber) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if(*current >= max) *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->bg = pCache->fg = -1; + pCache->orig_w = w; pCache->orig_h = h; + (*infoRec->WritePixmapToCache)( + pScrn, pCache->x, pCache->y, w, h, pPix->devPrivate.ptr, + pPix->devKind, pPix->drawable.bitsPerPixel, pPix->drawable.depth); + if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && + ((w != pCache->w) || (h != pCache->h))) + XAATileCache(pScrn, pCache, w, h); + + return pCache; +} + +XAACacheInfoPtr +XAACacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0, funcNo, pad, dwords, bpp = pScrn->bitsPerPixel; + int *current; + StippleScanlineProcPtr StippleFunc; + unsigned char *data, *srcPtr, *dstPtr; + + if((h <= 128) && (w <= 128 * bpp)) { + if(pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } else if((h <= 256) && (w <= 256 * bpp)){ + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } else if((h <= 512) && (w <= 526 * bpp)){ + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } else { /* something's wrong */ + ErrorF("Something's wrong in XAACacheMonoStipple()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + + /* lets look for it */ + for(i = 0; i < max; i++, pCache++) { + if((pCache->serialNumber == pPix->drawable.serialNumber) && + (pCache->fg == -1) && (pCache->bg == -1)) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if(*current >= max) *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->bg = pCache->fg = -1; + pCache->orig_w = w; pCache->orig_h = h; + + if(w <= 32) { + if(w & (w - 1)) funcNo = 1; + else funcNo = 0; + } else funcNo = 2; + + pad = BitmapBytePad(pCache->w * bpp); + dwords = bytes_to_int32(pad); + dstPtr = data = (unsigned char*)malloc(pad * pCache->h); + srcPtr = (unsigned char*)pPix->devPrivate.ptr; + + if(infoRec->ScreenToScreenColorExpandFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) + StippleFunc = XAAStippleScanlineFuncMSBFirst[funcNo]; + else + StippleFunc = XAAStippleScanlineFuncLSBFirst[funcNo]; + + /* don't bother generating more than we'll ever use */ + max = ((pScrn->displayWidth + w - 1) + 31) >> 5; + if(dwords > max) + dwords = max; + + for(i = 0; i < h; i++) { + (*StippleFunc)((CARD32*)dstPtr, (CARD32*)srcPtr, 0, w, dwords); + srcPtr += pPix->devKind; + dstPtr += pad; + } + + while((h<<1) <= pCache->h) { + memcpy(data + (pad * h), data, pad * h); + h <<= 1; + } + + if(h < pCache->h) + memcpy(data + (pad * h), data, pad * (pCache->h - h)); + + (*infoRec->WritePixmapToCache)( + pScrn, pCache->x, pCache->y, pCache->w, pCache->h, data, + pad, bpp, pScrn->depth); + + free(data); + + return pCache; +} + +XAACacheInfoPtr +XAACachePlanarMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0; + int *current; + + if((h <= 128) && (w <= 128)) { + if(pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } else if((h <= 256) && (w <= 256)){ + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } else if((h <= 512) && (w <= 526)){ + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } else { /* something's wrong */ + ErrorF("Something's wrong in XAACachePlanarMonoStipple()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + + /* lets look for it */ + for(i = 0; i < max; i++, pCache++) { + if((pCache->serialNumber == pPix->drawable.serialNumber) && + (pCache->fg == -1) && (pCache->bg == -1)) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if(*current >= max) *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->bg = pCache->fg = -1; + pCache->orig_w = w; pCache->orig_h = h; + + /* Plane 0 holds the stipple. Plane 1 holds the inverted stipple */ + (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, + pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr, + pPix->devKind, 1, 2); + if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_MONO_DATA) && + ((w != pCache->w) || (h != pCache->h))) + XAATileCache(pScrn, pCache, w, h); + + return pCache; +} + +XAACachePlanarMonoStippleProc +XAAGetCachePlanarMonoStipple(void) +{ + return XAACachePlanarMonoStipple; +} + +XAACacheInfoPtr +XAACacheStipple(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + int size = max(w, h); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0; + int *current; + + if(size <= 128) { + if(pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } else if(size <= 256) { + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } else if(size <= 512) { + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } else { /* something's wrong */ + ErrorF("Something's wrong in XAACacheStipple()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + /* lets look for it */ + if(bg == -1) + for(i = 0; i < max; i++, pCache++) { + if((pCache->serialNumber == pPix->drawable.serialNumber) && + (fg == pCache->fg) && (pCache->fg != pCache->bg)) { + pCache->trans_color = pCache->bg; + return pCache; + } + } + else + for(i = 0; i < max; i++, pCache++) { + if((pCache->serialNumber == pPix->drawable.serialNumber) && + (fg == pCache->fg) && (bg == pCache->bg)) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if(*current >= max) *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->fg = fg; + if(bg == -1) + pCache->trans_color = bg = fg ^ 1; + else + pCache->trans_color = -1; + pCache->bg = bg; + + pCache->orig_w = w; pCache->orig_h = h; + (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, + pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr, + pPix->devKind, fg, bg); + if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && + ((w != pCache->w) || (h != pCache->h))) + XAATileCache(pScrn, pCache, w, h); + + return pCache; +} + + + +XAACacheInfoPtr +XAACacheMono8x8Pattern(ScrnInfoPtr pScrn, int pat0, int pat1) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache = pCachePriv->InfoMono; + int i; + + for(i = 0; i < pCachePriv->NumMono; i++, pCache++) { + if(pCache->serialNumber && + (pCache->pat0 == pat0) && (pCache->pat1 == pat1)) + return pCache; + } + + /* OK, let's cache it */ + pCache = &pCachePriv->InfoMono[pCachePriv->CurrentMono++]; + if(pCachePriv->CurrentMono >= pCachePriv->NumMono) + pCachePriv->CurrentMono = 0; + + pCache->serialNumber = 1; /* we don't care since we do lookups by pattern */ + pCache->pat0 = pat0; + pCache->pat1 = pat1; + + (*infoRec->WriteMono8x8PatternToCache)(pScrn, pCache); + + return pCache; +} + + + +XAACacheInfoPtr +XAACacheColor8x8Pattern(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache = pCachePriv->InfoColor; + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + int i; + + if(!(pixPriv->flags & REDUCIBLE_TO_2_COLOR)) { + for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { + if(pCache->serialNumber == pPix->drawable.serialNumber) { + pCache->trans_color = -1; + return pCache; + } + } + pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; + if(pCachePriv->CurrentColor >= pCachePriv->NumColor) + pCachePriv->CurrentColor = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->fg = pCache->bg = -1; + } else { + int pat0 = pixPriv->pattern0; + int pat1 = pixPriv->pattern1; + + if(fg == -1) { /* it's a tile */ + fg = pixPriv->fg; bg = pixPriv->bg; + } + + if(bg == -1) { /* stipple */ + for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { + if(pCache->serialNumber && + (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && + (pCache->fg == fg) && (pCache->bg != fg)) { + pCache->trans_color = pCache->bg; + return pCache; + } + } + } else { /* opaque stipple */ + for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { + if(pCache->serialNumber && + (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && + (pCache->fg == fg) && (pCache->bg == bg)) { + pCache->trans_color = -1; + return pCache; + } + } + } + pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; + if(pCachePriv->CurrentColor >= pCachePriv->NumColor) + pCachePriv->CurrentColor = 0; + + if(bg == -1) + pCache->trans_color = bg = fg ^ 1; + else + pCache->trans_color = -1; + + pCache->pat0 = pat0; pCache->pat1 = pat1; + pCache->fg = fg; pCache->bg = bg; + pCache->serialNumber = 1; + } + + (*infoRec->WriteColor8x8PatternToCache)(pScrn, pPix, pCache); + + return pCache; +} + + +void +XAAWriteBitmapToCache( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int fg, int bg +) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->WriteBitmap)(pScrn, x, y, w, h, src, srcwidth, + 0, fg, bg, GXcopy, ~0); +} + +void +XAAWriteBitmapToCacheLinear( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int fg, int bg +){ + ScreenPtr pScreen = pScrn->pScreen; + PixmapPtr pScreenPix, pDstPix; + ChangeGCVal gcvals[2]; + GCPtr pGC; + + pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); + + pDstPix = GetScratchPixmapHeader(pScreen, pScreenPix->drawable.width, + y + h, pScreenPix->drawable.depth, + pScreenPix->drawable.bitsPerPixel, + pScreenPix->devKind, + pScreenPix->devPrivate.ptr); + + pGC = GetScratchGC(pScreenPix->drawable.depth, pScreen); + gcvals[0].val = fg; + gcvals[1].val = bg; + ChangeGC(NullClient, pGC, GCForeground | GCBackground, gcvals); + ValidateGC((DrawablePtr)pDstPix, pGC); + + /* We've unwrapped already so these ops miss a sync */ + SYNC_CHECK(pScrn); + + (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, 1, x, y, w, h, 0, + XYBitmap, (pointer)src); + + FreeScratchGC(pGC); + FreeScratchPixmapHeader(pDstPix); +} + + +void +XAAWritePixmapToCache( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int bpp, int depth +) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->WritePixmap)(pScrn, x, y, w, h, src, srcwidth, + GXcopy, ~0, -1, bpp, depth); +} + + + +void +XAAWritePixmapToCacheLinear( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int bpp, int depth +){ + ScreenPtr pScreen = pScrn->pScreen; + PixmapPtr pScreenPix, pDstPix; + GCPtr pGC; + + pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); + + pDstPix = GetScratchPixmapHeader(pScreen, x + w, y + h, + depth, bpp, pScreenPix->devKind, + pScreenPix->devPrivate.ptr); + + pGC = GetScratchGC(depth, pScreen); + ValidateGC((DrawablePtr)pDstPix, pGC); + + /* We've unwrapped already so these ops miss a sync */ + SYNC_CHECK(pScrn); + + if(bpp == BitsPerPixel(depth)) + (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, depth, x, y, w, + h, 0, ZPixmap, (pointer)src); + else { + PixmapPtr pSrcPix; + + pSrcPix = GetScratchPixmapHeader(pScreen, w, h, depth, bpp, + srcwidth, (pointer)src); + + (*pGC->ops->CopyArea)((DrawablePtr)pSrcPix, (DrawablePtr)pDstPix, + pGC, 0, 0, w, h, x, y); + + FreeScratchPixmapHeader(pSrcPix); + } + + FreeScratchGC(pGC); + FreeScratchPixmapHeader(pDstPix); +} + + +void +XAAWriteMono8x8PatternToCache( + ScrnInfoPtr pScrn, + XAACacheInfoPtr pCache +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + unsigned char *data; + int pad, Bpp = (pScrn->bitsPerPixel >> 3); + + pCache->offsets = pCachePriv->MonoOffsets; + + pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); + + data = (unsigned char*)malloc(pad * pCache->h); + if(!data) return; + + if(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { + CARD32* ptr = (CARD32*)data; + ptr[0] = pCache->pat0; ptr[1] = pCache->pat1; + } else { + CARD32 *ptr; + DDXPointPtr pPoint = pCache->offsets; + int patx, paty, i; + + for(i = 0; i < 64; i++, pPoint++) { + patx = pCache->pat0; paty = pCache->pat1; + XAARotateMonoPattern(&patx, &paty, i & 0x07, i >> 3, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + ptr = (CARD32*)(data + (pad * pPoint->y) + (Bpp * pPoint->x)); + ptr[0] = patx; ptr[1] = paty; + } + } + + (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y, + pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth); + + free(data); +} + +void +XAAWriteColor8x8PatternToCache( + ScrnInfoPtr pScrn, + PixmapPtr pPix, + XAACacheInfoPtr pCache +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + int pad, i, w, h, nw, nh, Bpp; + unsigned char *data, *srcPtr, *dstPtr; + + pCache->offsets = pCachePriv->ColorOffsets; + + if(pixPriv->flags & REDUCIBLE_TO_2_COLOR) { + CARD32* ptr; + pad = BitmapBytePad(pCache->w); + data = (unsigned char*)malloc(pad * pCache->h); + if(!data) return; + + if(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { + ptr = (CARD32*)data; + ptr[0] = pCache->pat0; ptr[1] = pCache->pat1; + } else { + int patx, paty; + + ptr = (CARD32*)data; + ptr[0] = ptr[2] = pCache->pat0; ptr[1] = ptr[3] = pCache->pat1; + for(i = 1; i < 8; i++) { + patx = pCache->pat0; paty = pCache->pat1; + XAARotateMonoPattern(&patx, &paty, i, 0, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + ptr = (CARD32*)(data + (pad * i)); + ptr[0] = ptr[2] = patx; ptr[1] = ptr[3] = paty; + } + } + + (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, + pCache->w, pCache->h, data, pad, pCache->fg, pCache->bg); + + free(data); + return; + } + + Bpp = pScrn->bitsPerPixel >> 3; + h = min(8,pPix->drawable.height); + w = min(8,pPix->drawable.width); + pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); + + data = (unsigned char*)malloc(pad * pCache->h); + if(!data) return; + + /* Write and expand horizontally. */ + for (i = h, dstPtr = data, srcPtr = pPix->devPrivate.ptr; i--; + srcPtr += pPix->devKind, dstPtr += pScrn->bitsPerPixel) { + nw = w; + memcpy(dstPtr, srcPtr, w * Bpp); + while (nw != 8) { + memcpy(dstPtr + (nw * Bpp), dstPtr, nw * Bpp); + nw <<= 1; + } + } + nh = h; + /* Expand vertically. */ + while (nh != 8) { + memcpy(data + (nh*pScrn->bitsPerPixel), data, nh*pScrn->bitsPerPixel); + nh <<= 1; + } + + if(!(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){ + int j; + unsigned char *ptr = data + (128 * Bpp); + + memcpy(data + (64 * Bpp), data, 64 * Bpp); + for(i = 1; i < 8; i++, ptr += (128 * Bpp)) { + for(j = 0; j < 8; j++) { + memcpy(ptr + (j * 8) * Bpp, data + (j * 8 + i) * Bpp, + (8 - i) * Bpp); + memcpy(ptr + (j * 8 + 8 - i) * Bpp, data + j * 8 * Bpp, i*Bpp); + } + memcpy(ptr + (64 * Bpp), ptr, 64 * Bpp); + } + } + + (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y, + pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth); + + free(data); +} + + + +int +XAAStippledFillChooser(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + PixmapPtr pPixmap = pGC->stipple; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + + if(!(pPriv->flags & REDUCIBILITY_CHECKED) && + (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { + XAACheckStippleReducibility(pPixmap); + } + + + if(pPriv->flags & REDUCIBLE_TO_8x8) { + if(infoRec->CanDoMono8x8 && + !(infoRec->FillMono8x8PatternSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillMono8x8PatternSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_FG(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { + + return DO_MONO_8x8; + } + + if(infoRec->CanDoColor8x8 && + !(infoRec->FillColor8x8PatternSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillColor8x8PatternSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { + + return DO_COLOR_8x8; + } + } + + if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / + infoRec->CacheColorExpandDensity) && + !(infoRec->FillCacheExpandSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillCacheExpandSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_FG(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) { + + return DO_CACHE_EXPAND; + } + + + if(infoRec->UsingPixmapCache && + !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && + infoRec->FillCacheBltSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && + !(infoRec->FillCacheBltSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillCacheBltSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { + + return DO_CACHE_BLT; + } + + if(infoRec->FillColorExpandSpans && + !(infoRec->FillColorExpandSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillColorExpandSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_FG(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) { + + return DO_COLOR_EXPAND; + } + + return 0; +} + + +int +XAAOpaqueStippledFillChooser(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + PixmapPtr pPixmap = pGC->stipple; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + + if(XAA_DEPTH_BUG(pGC)) + return 0; + + if(!(pPriv->flags & REDUCIBILITY_CHECKED) && + (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { + XAACheckStippleReducibility(pPixmap); + } + + if(pPriv->flags & REDUCIBLE_TO_8x8) { + if(infoRec->CanDoMono8x8 && + !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_COLORS(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { + + return DO_MONO_8x8; + } + + if(infoRec->CanDoColor8x8 && + CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { + + return DO_COLOR_8x8; + } + } + + if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / + infoRec->CacheColorExpandDensity) && + !(infoRec->FillCacheExpandSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_COLORS(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) { + + return DO_CACHE_EXPAND; + } + + if(infoRec->UsingPixmapCache && + !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && + infoRec->FillCacheBltSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && + CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { + + return DO_CACHE_BLT; + } + + if(infoRec->FillColorExpandSpans && + !(infoRec->FillColorExpandSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_COLORS(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) { + + return DO_COLOR_EXPAND; + } + + return 0; +} + + + +int +XAATiledFillChooser(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + PixmapPtr pPixmap = pGC->tile.pixmap; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + + if(IS_OFFSCREEN_PIXMAP(pPixmap) && infoRec->FillCacheBltSpans && + CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { + + return DO_PIXMAP_COPY; + } + + if(!(pPriv->flags & REDUCIBILITY_CHECKED) && + (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { + XAACheckTileReducibility(pPixmap,infoRec->CanDoMono8x8); + } + + if(pPriv->flags & REDUCIBLE_TO_8x8) { + if((pPriv->flags & REDUCIBLE_TO_2_COLOR) && infoRec->CanDoMono8x8 && + !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && + (!(infoRec->FillMono8x8PatternSpansFlags & RGB_EQUAL) || + (CHECK_RGB_EQUAL(pPriv->fg) && CHECK_RGB_EQUAL(pPriv->bg))) && + CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { + + return DO_MONO_8x8; + } + + if(infoRec->CanDoColor8x8 && + CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { + + return DO_COLOR_8x8; + } + } + + if(infoRec->UsingPixmapCache && infoRec->FillCacheBltSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && + CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { + + return DO_CACHE_BLT; + } + + if(infoRec->FillImageWriteRects && + CHECK_NO_GXCOPY(pGC,infoRec->FillImageWriteRectsFlags) && + CHECK_ROP(pGC,infoRec->FillImageWriteRectsFlags) && + CHECK_ROPSRC(pGC,infoRec->FillImageWriteRectsFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillImageWriteRectsFlags)) { + + return DO_IMAGE_WRITE; + } + + return 0; +} + + +static int RotateMasksX[8] = { + 0xFFFFFFFF, 0x7F7F7F7F, 0x3F3F3F3F, 0x1F1F1F1F, + 0x0F0F0F0F, 0x07070707, 0x03030303, 0x01010101 +}; + +static int RotateMasksY[4] = { + 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF +}; + +void +XAARotateMonoPattern( + int *pat0, int *pat1, + int xorg, int yorg, + Bool msbfirst +){ + int tmp, mask; + + if(xorg) { + if(msbfirst) xorg = 8 - xorg; + mask = RotateMasksX[xorg]; + *pat0 = ((*pat0 >> xorg) & mask) | ((*pat0 << (8 - xorg)) & ~mask); + *pat1 = ((*pat1 >> xorg) & mask) | ((*pat1 << (8 - xorg)) & ~mask); + } + if(yorg >= 4) { + tmp = *pat0; *pat0 = *pat1; *pat1 = tmp; + yorg -= 4; + } + if(yorg) { + mask = RotateMasksY[yorg]; + yorg <<= 3; + tmp = *pat0; + *pat0 = ((*pat0 >> yorg) & mask) | ((*pat1 << (32 - yorg)) & ~mask); + *pat1 = ((*pat1 >> yorg) & mask) | ((tmp << (32 - yorg)) & ~mask); + } +} + + + +void +XAAInvalidatePixmapCache(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + int i; + + if(!pCachePriv) return; + + for(i = 0; i < pCachePriv->Num512x512; i++) + (pCachePriv->Info512)[i].serialNumber = 0; + for(i = 0; i < pCachePriv->Num256x256; i++) + (pCachePriv->Info256)[i].serialNumber = 0; + for(i = 0; i < pCachePriv->Num128x128; i++) + (pCachePriv->Info128)[i].serialNumber = 0; + for(i = 0; i < pCachePriv->NumPartial; i++) + (pCachePriv->InfoPartial)[i].serialNumber = 0; + for(i = 0; i < pCachePriv->NumMono; i++) + (pCachePriv->InfoMono)[i].serialNumber = 0; + for(i = 0; i < pCachePriv->NumColor; i++) + (pCachePriv->InfoColor)[i].serialNumber = 0; +} -- cgit v1.2.3