#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <string.h>
#include "misc.h"
#include "xf86.h"
#include "xf86_OSproc.h"
#include <X11/X.h>
#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)
{
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;
free(pPriv->Info512);
free(pPriv->Info256);
free(pPriv->Info128);
free(pPriv->InfoColor);
free(pPriv->InfoMono);
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
) {
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;
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;
}
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:
if(List64) FreeList(List64);
if(List32) FreeList(List32);
if(List16) FreeList(List16);
if(List8) FreeList(List8);
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
){
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) {
if(MonoH > ColorH) ColorH = MonoH;
if(MonoW > ColorW) ColorW = MonoW;
}
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
){
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) {
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;
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;
}
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);
}
}
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:
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);
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 = RegionRects(areas);
int nBox = RegionNumRects(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;
if (CacheInitIndex < 0)
CacheInitIndex = xf86AllocateScrnInfoPrivateIndex();
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;
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++;
}
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) {
} 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) {
} 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;
next = List128->next;
while(Num128 > max) {
List128->next = ListPartial;
ListPartial = List128;
if((List128 = next))
next = List128->next;
NumPartial++; Num128--;
}
}
MaxPartialHeight = MaxPartialWidth = 0;
if(!(infoRec->PixmapCacheFlags & (CACHE_MONO_8x8 | CACHE_COLOR_8x8))) {
if(NumPartial) {
if(Num128) {
FreeList(ListPartial);
NumPartial = 0; ListPartial = NULL;
} else {
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) {
if(MonoH > ColorH) ColorH = MonoH;
if(MonoW > ColorW) ColorW = MonoW;
MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW);
}
if(Num128) {
if(NumPartial) {
ConvertAllPartialsTo8x8(&NumMono, &NumColor,
ListPartial, &ListMono, &ListColor, infoRec);
NumPartial = 0; ListPartial = NULL;
}
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) {
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;
}
}
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;
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 {
ErrorF("Something's wrong in XAACacheTile()\n");
return pCachePriv->Info128;
}
pCache = cacheRoot;
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 {
ErrorF("Something's wrong in XAACacheMonoStipple()\n");
return pCachePriv->Info128;
}
pCache = cacheRoot;
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];
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 {
ErrorF("Something's wrong in XAACachePlanarMonoStipple()\n");
return pCachePriv->Info128;
}
pCache = cacheRoot;
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;
(*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 {
ErrorF("Something's wrong in XAACacheStipple()\n");
return pCachePriv->Info128;
}
pCache = cacheRoot;
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;
}
pCache = &pCachePriv->InfoMono[pCachePriv->CurrentMono++];
if(pCachePriv->CurrentMono >= pCachePriv->NumMono)
pCachePriv->CurrentMono = 0;
pCache->serialNumber = 1;
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) {
fg = pixPriv->fg; bg = pixPriv->bg;
}
if(bg == -1) {
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 {
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);
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);
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;
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;
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;
}