#include "fb.h"
#ifdef IN_MODULE
#include "xf86_ansic.h"
#endif
const GCFuncs fbGCFuncs = {
fbValidateGC,
miChangeGC,
miCopyGC,
miDestroyGC,
miChangeClip,
miDestroyClip,
miCopyClip,
};
const GCOps fbGCOps = {
fbFillSpans,
fbSetSpans,
fbPutImage,
fbCopyArea,
fbCopyPlane,
fbPolyPoint,
fbPolyLine,
fbPolySegment,
fbPolyRectangle,
fbPolyArc,
miFillPolygon,
fbPolyFillRect,
fbPolyFillArc,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
fbImageGlyphBlt,
fbPolyGlyphBlt,
fbPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
Bool
fbCreateGC(GCPtr pGC)
{
pGC->clientClip = NULL;
pGC->clientClipType = CT_NONE;
pGC->ops = (GCOps *) &fbGCOps;
pGC->funcs = (GCFuncs *) &fbGCFuncs;
pGC->miTranslate = 1;
fbGetRotatedPixmap(pGC) = 0;
fbGetExpose(pGC) = 1;
fbGetFreeCompClip(pGC) = 0;
fbGetCompositeClip(pGC) = 0;
fbGetGCPrivate(pGC)->bpp = BitsPerPixel (pGC->depth);
return TRUE;
}
void
fbPadPixmap (PixmapPtr pPixmap)
{
int width;
FbBits *bits;
FbBits b;
FbBits mask;
int height;
int w;
width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel;
bits = pPixmap->devPrivate.ptr;
height = pPixmap->drawable.height;
mask = FbBitsMask (0, width);
while (height--)
{
b = *bits & mask;
w = width;
while (w < FB_UNIT)
{
b = b | FbScrRight(b, w);
w <<= 1;
}
*bits++ = b;
}
}
static Bool
fbBitsRepeat (FbBits bits, int len, int width)
{
FbBits mask = FbBitsMask(0, len);
FbBits orig = bits & mask;
int i;
if (width > FB_UNIT)
width = FB_UNIT;
for (i = 0; i < width / len; i++)
{
if ((bits & mask) != orig)
return FALSE;
bits = FbScrLeft(bits,len);
}
return TRUE;
}
static Bool
fbLineRepeat (FbBits *bits, int len, int width)
{
FbBits first = bits[0];
if (!fbBitsRepeat (first, len, width))
return FALSE;
width = (width + FB_UNIT-1) >> FB_SHIFT;
bits++;
while (--width)
if (*bits != first)
return FALSE;
return TRUE;
}
static Bool
fbCanEvenStipple (PixmapPtr pStipple, int bpp)
{
int len = FB_UNIT / bpp;
FbBits *bits;
int stride;
int stip_bpp;
int stipXoff, stipYoff;
int h;
if ((bpp & (bpp-1)) != 0)
return FALSE;
if (pStipple->drawable.width % len != 0)
return FALSE;
fbGetDrawable (&pStipple->drawable, bits, stride, stip_bpp, stipXoff, stipYoff);
h = pStipple->drawable.height;
while (h--)
{
if (!fbLineRepeat (bits, len, pStipple->drawable.width))
return FALSE;
bits += stride;
}
return TRUE;
}
void
fbValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
{
FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
FbBits mask;
pGC->lastWinOrg.x = pDrawable->x;
pGC->lastWinOrg.y = pDrawable->y;
if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
(pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
)
{
miComputeCompositeClip (pGC, pDrawable);
pPriv->oneRect = REGION_NUM_RECTS(fbGetCompositeClip(pGC)) == 1;
}
#ifdef FB_24_32BIT
if (pPriv->bpp != pDrawable->bitsPerPixel)
{
changes |= GCStipple|GCForeground|GCBackground|GCPlaneMask;
pPriv->bpp = pDrawable->bitsPerPixel;
}
if ((changes & GCTile) && fbGetRotatedPixmap(pGC))
{
(*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC));
fbGetRotatedPixmap(pGC) = 0;
}
if (pGC->fillStyle == FillTiled)
{
PixmapPtr pOldTile, pNewTile;
pOldTile = pGC->tile.pixmap;
if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
{
pNewTile = fbGetRotatedPixmap(pGC);
if (!pNewTile || pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel)
{
if (pNewTile)
(*pGC->pScreen->DestroyPixmap) (pNewTile);
pNewTile = fb24_32ReformatTile (pOldTile, pDrawable->bitsPerPixel);
}
if (pNewTile)
{
fbGetRotatedPixmap(pGC) = pOldTile;
pGC->tile.pixmap = pNewTile;
changes |= GCTile;
}
}
}
#endif
if (changes & GCTile)
{
if (!pGC->tileIsPixel &&
FbEvenTile (pGC->tile.pixmap->drawable.width *
pDrawable->bitsPerPixel))
fbPadPixmap (pGC->tile.pixmap);
}
if (changes & GCStipple)
{
pPriv->evenStipple = FALSE;
if (pGC->stipple) {
if (FbEvenStip (pGC->stipple->drawable.width,
pDrawable->bitsPerPixel) &&
(fbCanEvenStipple (pGC->stipple, pDrawable->bitsPerPixel)))
pPriv->evenStipple = TRUE;
if (pGC->stipple->drawable.width * pDrawable->bitsPerPixel < FB_UNIT)
fbPadPixmap (pGC->stipple);
}
}
if (changes & (GCForeground|GCBackground|GCPlaneMask|GCFunction))
{
int s;
FbBits depthMask;
mask = FbFullMask(pDrawable->bitsPerPixel);
depthMask = FbFullMask(pDrawable->depth);
pPriv->fg = pGC->fgPixel & mask;
pPriv->bg = pGC->bgPixel & mask;
if ((pGC->planemask & depthMask) == depthMask)
pPriv->pm = mask;
else
pPriv->pm = pGC->planemask & mask;
s = pDrawable->bitsPerPixel;
while (s < FB_UNIT)
{
pPriv->fg |= pPriv->fg << s;
pPriv->bg |= pPriv->bg << s;
pPriv->pm |= pPriv->pm << s;
s <<= 1;
}
pPriv->and = fbAnd(pGC->alu, pPriv->fg, pPriv->pm);
pPriv->xor = fbXor(pGC->alu, pPriv->fg, pPriv->pm);
pPriv->bgand = fbAnd(pGC->alu, pPriv->bg, pPriv->pm);
pPriv->bgxor = fbXor(pGC->alu, pPriv->bg, pPriv->pm);
}
if (changes & GCDashList)
{
unsigned short n = pGC->numInDashList;
unsigned char *dash = pGC->dash;
unsigned int dashLength = 0;
while (n--)
dashLength += (unsigned int ) *dash++;
pPriv->dashLength = dashLength;
}
}