David Dawes
dawes****@XFree*****
2003年 8月 15日 (金) 10:55:37 JST
On Thu, Aug 14, 2003 at 04:17:41PM -0700, Mark Vojkovich wrote: >On Thu, 14 Aug 2003, David Dawes wrote: > >> > >> > XAACacheTile() should have never been called if no slots existed. >> >MaxCacheableTileWidth and MaxCacheableTileHeight should have been >> >consulted at some point. >> >> OK, we need to see what those values are at this point. XAAPaintWindow(), >> where the crash is apparently happening, does have a test for them, so >> maybe there's getting set incorrectly somewhere. >> >> if(infoRec->UsingPixmapCache && >> infoRec->FillCacheBltRects && !NoCache && >> ((what == PW_BORDER) || >> (pPix->drawable.height != pWin->drawable.height) || >> (pPix->drawable.width != pWin->drawable.width)) && >> (pPix->drawable.height <= infoRec->MaxCacheableTileHeight) && >> (pPix->drawable.width <= infoRec->MaxCacheableTileWidth)) { >> >> XAACacheInfoPtr pCache = >> (*infoRec->CacheTile)(infoRec->pScrn, pPix); >> (*infoRec->FillCacheBltRects)(infoRec->pScrn, GXcopy, ~0, >> nBox, pBox, xorg, yorg, pCache); >> return; >> } >> >> This check assumes that if there are no 256x256 slots there won't >> be any 512x512 slots. I'm not 100% sure if it can ever happen that >> there are 512x512 slots but no 256x256 slots. If the debugging >> could be extended to print both infoRec->MaxCacheableTileHeight >> and Num512, it should clarify if this is the problem or not. > > It's expected that if there are 512x512 slots there will be >smaller slots. The logic that sets up the slots in XAAInitPixmapCache >is supposed to ensure that. I played around a little with some unusual cases. If the memory is very fragmented, I can find a case where there are 4 512x512 slots and no 256x256 slots. The trick here is to have enough boxes for 4 512 slots and lots of 128 slots, but none for any 256 slots to get allocated in the first round. If there are enough 128x128 slots, the target for 512x512 slots will remain at 4 and none of them get split into 256x256 slots. A case that gives this result is 4 512x512 boxes and 70 250x250 boxes: 128: 32, 256: 0, 512: 4, partial: 288 max cacheable: 512x512 I've attached the test program I used to look at various cases. David -------------- next part -------------- #define MAX_128 32 #define MAX_256 32 #define MAX_512 16 void XAAInitPixmapCache(int *xin, int *yin, int nBox) { int Num512, Num256, Num128, NumPartial, NumColor, NumMono; int Target512, Target256; int x, y, w, h, ntotal, granularity, width, height, i; int MaxPartialWidth, MaxPartialHeight; int MaxCacheableTileWidth, MaxCacheableTileHeight; int x1 = 0, y1 = 0; int x2, y2; MaxCacheableTileWidth = 0; MaxCacheableTileHeight = 0; Num512 = Num256 = Num128 = NumPartial = NumMono = NumColor = 0; granularity = 0; /* go through the boxes and break it into as many pieces as we can fit */ printf("nBox: %d\n"); while(nBox--) { x2 = xin[nBox]; y2 = yin[nBox]; x = x1; if(granularity) { int tmp = x % granularity; if(tmp) x += (granularity - tmp); } width = x2 - x; if(width <= 0) {continue;} y = y1; height = y2 - y; for(h = 0; h <= (height - 512); h += 512) { for(w = 0; w <= (width - 512); w += 512) { Num512++; printf("Num512 -> %d\n", Num512); } for(; w <= (width - 256); w += 256) { Num256 += 2; printf("Num256 -> %d\n", Num256); } for(; w <= (width - 128); w += 128) { Num128 += 4; printf("Num128 -> %d\n", Num128); } if(w < width) { int d = width - w; NumPartial += 4; } } for(; h <= (height - 256); h += 256) { for(w = 0; w <= (width - 256); w += 256) { Num256++; printf("Num256 -> %d\n", Num256); } for(; w <= (width - 128); w += 128) { Num128 += 2; printf("Num128 -> %d\n", Num128); } if(w < width) { int d = width - w; NumPartial += 2; } } for(; h <= (height - 128); h += 128) { for(w = 0; w <= (width - 128); w += 128) { Num128++; printf("Num128 -> %d\n", Num128); } if(w < width) { NumPartial++; } } if(h < height) { int d = height - h; for(w = 0; w <= (width - 128); w += 128) { NumPartial++; } if(w < width) { NumPartial++; } } } /* 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. 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; printf("Targets: 512: %d, 256: %d\n", Target512, Target256); if(!Num512) { /* no room */ } else if((Num512 < 4) || (!Target512)) { while(Num512) { Num256 += 4; Num512--; printf("Num512 -> %d\n", Num512); printf("Num256 -> %d\n", Num256); } } else if((Num512 > MAX_512) || (Num512 > Target512)){ while(Num512 > MAX_512) { Num256 += 4; Num512--; printf("Num512 -> %d\n", Num512); printf("Num256 -> %d\n", Num256); } while(Num512 > Target512) { if(Num256 < MAX_256) { Num256 += 4; Num512--; printf("Num512 -> %d\n", Num512); printf("Num256 -> %d\n", Num256); } else break; } } if(!Num256) { /* no room */ } else if((Num256 < 4) || (!Target256)) { while(Num256) { Num128 += 4; Num256--; printf("Num256 -> %d\n", Num256); printf("Num128 -> %d\n", Num128); } } else if((Num256 > MAX_256) || (Num256 > Target256)) { while(Num256 > MAX_256) { Num128 += 4; Num256--; printf("Num256 -> %d\n", Num256); printf("Num128 -> %d\n", Num128); } while(Num256 > Target256) { if(Num128 < MAX_128) { Num128 += 4; Num256--; printf("Num256 -> %d\n", Num256); printf("Num128 -> %d\n", Num128); } else break; } } if(Num128 && ((Num128 < 4) || (Num128 > MAX_128))) { 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. */ while(Num128 > max) { NumPartial++; Num128--; printf("Num128 -> %d\n", Num128); } } MaxPartialHeight = MaxPartialWidth = 0; if(Num128) MaxCacheableTileWidth = MaxCacheableTileHeight = 128; if(Num256) MaxCacheableTileWidth = MaxCacheableTileHeight = 256; if(Num512) MaxCacheableTileWidth = MaxCacheableTileHeight = 512; printf("128: %d, 256: %d, 512: %d, partial: %d\n", Num128, Num256, Num512, NumPartial); printf("max cacheable: %dx%d\n", MaxCacheableTileWidth, MaxCacheableTileHeight); } main() { #define MAX_I 100 int x[MAX_I], y[MAX_I], i, n; while (1) { i = 0; do { printf("Enter width, height, num: (0 0 0 to end)\n"); scanf("%d %d %d", &(x[i]), &(y[i]), &n); i++; if (n) { while (--n && i < MAX_I) { x[i] = x[i - 1]; y[i] = y[i - 1]; i++; } } } while (x[i - 1] != 0 && i < MAX_I); XAAInitPixmapCache(x, y, i); } }