xserver-multidpi/hw/kdrive/igs/igsdraw.c

1539 lines
35 KiB
C

/*
* $RCSId: xc/programs/Xserver/hw/kdrive/igs/igsdraw.c,v 1.1 2000/05/06 22:17:43 keithp Exp $
*
* Copyright © 2000 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <kdrive-config.h>
#endif
#include "igs.h"
#include "igsdraw.h"
#include "Xmd.h"
#include "gcstruct.h"
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "regionstr.h"
#include "mistruct.h"
#include "fontstruct.h"
#include "dixfontstr.h"
#include "fb.h"
#include "migc.h"
#include "miline.h"
CARD8 igsPatRop[16] = {
/* GXclear */ 0x00, /* 0 */
/* GXand */ 0xa0, /* src AND dst */
/* GXandReverse */ 0x50, /* src AND NOT dst */
/* GXcopy */ 0xf0, /* src */
/* GXandInverted*/ 0x0a, /* NOT src AND dst */
/* GXnoop */ 0xaa, /* dst */
/* GXxor */ 0x5a, /* src XOR dst */
/* GXor */ 0xfa, /* src OR dst */
/* GXnor */ 0x05, /* NOT src AND NOT dst */
/* GXequiv */ 0xa5, /* NOT src XOR dst */
/* GXinvert */ 0x55, /* NOT dst */
/* GXorReverse */ 0xf5, /* src OR NOT dst */
/* GXcopyInverted*/ 0x0f, /* NOT src */
/* GXorInverted */ 0xaf, /* NOT src OR dst */
/* GXnand */ 0x5f, /* NOT src OR NOT dst */
/* GXset */ 0xff, /* 1 */
};
/*
* Handle pixel transfers
*/
#define BURST
#ifdef BURST
#define PixTransDeclare VOL32 *pix_trans_base = igsc->copData,\
*pix_trans = pix_trans_base
#define PixTransStart(n) if (pix_trans + (n) > pix_trans_base + 16384) pix_trans = pix_trans_base
#define PixTransStore(t) *pix_trans++ = (t)
#else
#define PixTransDeclare VOL32 *pix_trans = igsc->copData
#define PixTransStart(n)
#define PixTransStore(t) *pix_trans = (t)
#endif
static IgsPattern *
igsSetPattern (ScreenPtr pScreen,
PixmapPtr pPixmap,
CARD8 fillStyle,
INT32 xrot,
INT32 yrot)
{
KdScreenPriv(pScreen);
igsCardInfo(pScreenPriv);
igsScreenInfo(pScreenPriv);
int i;
IgsPatternCache *c;
IgsPattern *p;
if (fillStyle == FillTiled)
c = &igss->tile;
else
c = &igss->stipple;
for (i = 0; i < IGS_NUM_PATTERN; i++)
{
p = &c->pattern[i];
if (p->serial_number == pPixmap->drawable.serialNumber &&
p->xrot == xrot &&
p->yrot == yrot)
{
return p;
}
}
p = &c->pattern[c->next];
if (++c->next == IGS_NUM_PATTERN)
c->next = 0;
p->serial_number = pPixmap->drawable.serialNumber;
p->xrot = xrot;
p->yrot = yrot;
if (fillStyle != FillTiled)
{
FbStip *pix;
FbStride pixStride;
int pixBpp;
int pixXoff, pixYoff;
CARD8 tmp[8];
CARD32 *pat;
int stipX, stipY;
int y;
FbStip bits;
fbGetStipDrawable (&pPixmap->drawable, pix, pixStride, pixBpp, pixXoff, pixYoff);
modulus (-yrot - pixYoff, pPixmap->drawable.height, stipY);
modulus (-xrot - pixXoff, FB_UNIT, stipX);
pat = (CARD32 *) p->base;
for (y = 0; y < 8; y++)
{
bits = pix[stipY * pixStride];
FbRotLeft (bits, stipX);
tmp[y] = (CARD8) bits;
stipY++;
if (stipY == pPixmap->drawable.height)
stipY = 0;
}
for (i = 0; i < 2; i++)
{
bits = (tmp[i*4+0] |
(tmp[i*4+1] << 8) |
(tmp[i*4+2] << 16) |
(tmp[i*4+3] << 24));
IgsAdjustBits32 (bits);
*pat++ = bits;
}
}
else
{
FbBits *pix;
FbStride pixStride;
int pixBpp;
FbBits *pat;
FbStride patStride;
int patBpp;
int patXoff, patYoff;
fbGetDrawable (&pPixmap->drawable, pix, pixStride, pixBpp, patXoff, patYoff);
pat = (FbBits *) p->base;
patBpp = pixBpp;
patStride = (patBpp * IGS_PATTERN_WIDTH) / (8 * sizeof (FbBits));
fbTile (pat, patStride, 0,
patBpp * IGS_PATTERN_WIDTH, IGS_PATTERN_HEIGHT,
pix, pixStride,
pPixmap->drawable.width * pixBpp,
pPixmap->drawable.height,
GXcopy, FB_ALLONES, pixBpp,
(xrot - patXoff) * pixBpp, yrot - patYoff);
}
return p;
}
void
igsFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox,
unsigned long pixel, int alu, unsigned long planemask)
{
SetupIgs(pDrawable->pScreen);
CARD32 cmd;
_igsSetSolidRect(cop,alu,planemask,pixel,cmd);
while (nBox--)
{
_igsRect(cop,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd);
pBox++;
}
KdMarkSync (pDrawable->pScreen);
}
void
igsFillBoxTiled (DrawablePtr pDrawable, int nBox, BoxPtr pBox,
PixmapPtr pPixmap, int xrot, int yrot, int alu)
{
SetupIgs(pDrawable->pScreen);
CARD32 cmd;
IgsPattern *p = igsSetPattern (pDrawable->pScreen,
pPixmap,
FillTiled,
xrot, yrot);
_igsSetTiledRect(cop,alu,planemask,p->offset,cmd);
while (nBox--)
{
_igsPatRect(cop,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd);
pBox++;
}
KdMarkSync (pDrawable->pScreen);
}
void
igsFillBoxStippled (DrawablePtr pDrawable, GCPtr pGC,
int nBox, BoxPtr pBox)
{
SetupIgs(pDrawable->pScreen);
CARD32 cmd;
int xrot = pGC->patOrg.x + pDrawable->x;
int yrot = pGC->patOrg.y + pDrawable->y;
IgsPattern *p = igsSetPattern (pDrawable->pScreen,
pGC->stipple,
pGC->fillStyle,
xrot, yrot);
if (pGC->fillStyle == FillStippled)
{
_igsSetStippledRect (cop,pGC->alu,planemask,pGC->fgPixel,p->offset,cmd);
}
else
{
_igsSetOpaqueStippledRect (cop,pGC->alu,planemask,
pGC->fgPixel,pGC->bgPixel,p->offset,cmd);
}
while (nBox--)
{
_igsPatRect(cop,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd);
pBox++;
}
KdMarkSync (pDrawable->pScreen);
}
void
igsStipple (ScreenPtr pScreen,
CARD32 cmd,
FbStip *psrcBase,
FbStride widthSrc,
int srcx,
int srcy,
int dstx,
int dsty,
int width,
int height)
{
SetupIgs(pScreen);
FbStip *psrcLine, *psrc;
FbStride widthRest;
FbStip bits, tmp, lastTmp;
int leftShift, rightShift;
int nl, nlMiddle;
int r;
PixTransDeclare;
/* Compute blt address and parameters */
psrc = psrcBase + srcy * widthSrc + (srcx >> 5);
nlMiddle = (width + 31) >> 5;
leftShift = srcx & 0x1f;
rightShift = 32 - leftShift;
widthRest = widthSrc - nlMiddle;
_igsPlaneBlt(cop,dstx,dsty,width,height,cmd);
if (leftShift == 0)
{
while (height--)
{
nl = nlMiddle;
PixTransStart(nl);
while (nl--)
{
tmp = *psrc++;
IgsAdjustBits32 (tmp);
PixTransStore (tmp);
}
psrc += widthRest;
}
}
else
{
widthRest--;
while (height--)
{
bits = *psrc++;
nl = nlMiddle;
PixTransStart(nl);
while (nl--)
{
tmp = FbStipLeft(bits, leftShift);
bits = *psrc++;
tmp |= FbStipRight(bits, rightShift);
IgsAdjustBits32(tmp);
PixTransStore (tmp);
}
psrc += widthRest;
}
}
}
void
igsCopyNtoN (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
GCPtr pGC,
BoxPtr pbox,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure)
{
SetupIgs(pDstDrawable->pScreen);
int srcX, srcY, dstX, dstY;
int w, h;
CARD32 flags;
CARD32 cmd;
CARD8 alu;
if (pGC)
{
alu = pGC->alu;
if (sourceInvarient (pGC->alu))
{
igsFillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu, pGC->planemask);
return;
}
}
else
alu = GXcopy;
_igsSetBlt(cop,alu,pGC->planemask,reverse,upsidedown,cmd);
while (nbox--)
{
w = pbox->x2 - pbox->x1;
h = pbox->y2 - pbox->y1;
if (reverse)
dstX = pbox->x2 - 1;
else
dstX = pbox->x1;
srcX = dstX + dx;
if (upsidedown)
dstY = pbox->y2 - 1;
else
dstY = pbox->y1;
srcY = dstY + dy;
_igsBlt (cop, srcX, srcY, dstX, dstY, w, h, cmd);
pbox++;
}
KdMarkSync (pDstDrawable->pScreen);
}
RegionPtr
igsCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
int srcx, int srcy, int width, int height, int dstx, int dsty)
{
KdScreenPriv(pDstDrawable->pScreen);
FbBits depthMask;
depthMask = FbFullMask (pDstDrawable->depth);
if ((pGC->planemask & depthMask) == depthMask &&
pSrcDrawable->type == DRAWABLE_WINDOW &&
pDstDrawable->type == DRAWABLE_WINDOW)
{
return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
srcx, srcy, width, height,
dstx, dsty, igsCopyNtoN, 0, 0);
}
return KdCheckCopyArea (pSrcDrawable, pDstDrawable, pGC,
srcx, srcy, width, height, dstx, dsty);
}
typedef struct _igs1toNargs {
unsigned long copyPlaneFG, copyPlaneBG;
Bool opaque;
} igs1toNargs;
void
igsCopy1toN (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
GCPtr pGC,
BoxPtr pbox,
int nbox,
int dx,
int dy,
Bool reverse,
Bool upsidedown,
Pixel bitplane,
void *closure)
{
SetupIgs(pDstDrawable->pScreen);
igs1toNargs *args = closure;
int dstx, dsty;
FbStip *psrcBase;
FbStride widthSrc;
int srcBpp;
int srcXoff, srcYoff;
CARD32 cmd;
if (args->opaque && sourceInvarient (pGC->alu))
{
igsFillBoxSolid (pDstDrawable, nbox, pbox,
pGC->bgPixel, pGC->alu, pGC->planemask);
return;
}
fbGetStipDrawable (pSrcDrawable, psrcBase, widthSrc, srcBpp, srcXoff, srcYoff);
if (args->opaque)
{
_igsSetOpaquePlaneBlt (cop, pGC->alu, pGC->planemask, args->copyPlaneFG,
args->copyPlaneBG, cmd);
}
else
{
_igsSetTransparentPlaneBlt (cop, pGC->alu, pGC->planemask,
args->copyPlaneFG, cmd);
}
while (nbox--)
{
dstx = pbox->x1;
dsty = pbox->y1;
igsStipple (pDstDrawable->pScreen, cmd,
psrcBase, widthSrc,
dstx + dx - srcXoff, dsty + dy - srcYoff,
dstx, dsty,
pbox->x2 - dstx, pbox->y2 - dsty);
pbox++;
}
KdMarkSync (pDstDrawable->pScreen);
}
RegionPtr
igsCopyPlane (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
GCPtr pGC,
int srcx,
int srcy,
int width,
int height,
int dstx,
int dsty,
unsigned long bitPlane)
{
RegionPtr ret;
igs1toNargs args;
FbBits depthMask;
depthMask = FbFullMask (pDstDrawable->depth);
if ((pGC->planemask & depthMask) == depthMask &&
pDstDrawable->type == DRAWABLE_WINDOW &&
pSrcDrawable->depth == 1)
{
args.copyPlaneFG = pGC->fgPixel;
args.copyPlaneBG = pGC->bgPixel;
args.opaque = TRUE;
return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
srcx, srcy, width, height,
dstx, dsty, igsCopy1toN, bitPlane, &args);
}
return KdCheckCopyPlane(pSrcDrawable, pDstDrawable, pGC,
srcx, srcy, width, height,
dstx, dsty, bitPlane);
}
#if 0
/* would you believe this is slower than fb? */
void
igsPushPixels (GCPtr pGC,
PixmapPtr pBitmap,
DrawablePtr pDrawable,
int w,
int h,
int x,
int y)
{
igs1toNargs args;
FbBits depthMask;
depthMask = FbFullMask (pDstDrawable->depth);
if ((pGC->planemask & depthMask) == depthMask &&
pDrawable->type == DRAWABLE_WINDOW &&
pGC->fillStyle == FillSolid)
{
args.opaque = FALSE;
args.copyPlaneFG = pGC->fgPixel;
(void) fbDoCopy ((DrawablePtr) pBitmap, pDrawable, pGC,
0, 0, w, h, x, y, igsCopy1toN, 1, &args);
}
else
{
KdCheckPushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
}
}
#else
#define igsPushPixels KdCheckPushPixels
#endif
BOOL
igsFillOk (GCPtr pGC)
{
FbBits depthMask;
depthMask = FbFullMask(pGC->depth);
if ((pGC->planemask & depthMask) != depthMask)
return FALSE;
switch (pGC->fillStyle) {
case FillSolid:
return TRUE;
case FillTiled:
return (igsPatternDimOk (pGC->tile.pixmap->drawable.width) &&
igsPatternDimOk (pGC->tile.pixmap->drawable.height));
case FillStippled:
case FillOpaqueStippled:
return (igsPatternDimOk (pGC->stipple->drawable.width) &&
igsPatternDimOk (pGC->stipple->drawable.height));
}
return FALSE;
}
void
igsFillSpans (DrawablePtr pDrawable, GCPtr pGC, int n,
DDXPointPtr ppt, int *pwidth, int fSorted)
{
SetupIgs(pDrawable->pScreen);
DDXPointPtr pptFree;
FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
int *pwidthFree;/* copies of the pointers to free */
CARD32 cmd;
int nTmp;
INT16 x, y;
int width;
IgsPattern *p;
if (!igsFillOk (pGC))
{
KdCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
return;
}
nTmp = n * miFindMaxBand(fbGetCompositeClip(pGC));
pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int));
pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec));
if(!pptFree || !pwidthFree)
{
if (pptFree) DEALLOCATE_LOCAL(pptFree);
if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
return;
}
n = miClipSpans(fbGetCompositeClip(pGC),
ppt, pwidth, n,
pptFree, pwidthFree, fSorted);
pwidth = pwidthFree;
ppt = pptFree;
switch (pGC->fillStyle) {
case FillSolid:
_igsSetSolidRect(cop,pGC->alu,pGC->planemask,pGC->fgPixel,cmd);
break;
case FillTiled:
p = igsSetPattern (pDrawable->pScreen,
pGC->tile.pixmap,
FillTiled,
pGC->patOrg.x + pDrawable->x,
pGC->patOrg.y + pDrawable->y);
_igsSetTiledRect (cop,pGC->alu,pGC->planemask,p->offset,cmd);
break;
default:
p = igsSetPattern (pDrawable->pScreen,
pGC->stipple,
pGC->fillStyle,
pGC->patOrg.x + pDrawable->x,
pGC->patOrg.y + pDrawable->y);
if (pGC->fillStyle == FillStippled)
{
_igsSetStippledRect (cop,pGC->alu,pGC->planemask,
pGC->fgPixel,p->offset,cmd);
}
else
{
_igsSetOpaqueStippledRect (cop,pGC->alu,pGC->planemask,
pGC->fgPixel,pGC->bgPixel,p->offset,cmd);
}
break;
}
while (n--)
{
x = ppt->x;
y = ppt->y;
ppt++;
width = *pwidth++;
if (width)
{
_igsPatRect(cop,x,y,width,1,cmd);
}
}
DEALLOCATE_LOCAL(pptFree);
DEALLOCATE_LOCAL(pwidthFree);
KdMarkSync (pDrawable->pScreen);
}
#define NUM_STACK_RECTS 1024
void
igsPolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
int nrectFill, xRectangle *prectInit)
{
SetupIgs(pDrawable->pScreen);
xRectangle *prect;
RegionPtr prgnClip;
register BoxPtr pbox;
register BoxPtr pboxClipped;
BoxPtr pboxClippedBase;
BoxPtr pextent;
BoxRec stackRects[NUM_STACK_RECTS];
FbGCPrivPtr fbPriv = fbGetGCPrivate (pGC);
int numRects;
int n;
int xorg, yorg;
int x, y;
if (!igsFillOk (pGC))
{
KdCheckPolyFillRect (pDrawable, pGC, nrectFill, prectInit);
return;
}
prgnClip = fbGetCompositeClip (pGC);
xorg = pDrawable->x;
yorg = pDrawable->y;
if (xorg || yorg)
{
prect = prectInit;
n = nrectFill;
while(n--)
{
prect->x += xorg;
prect->y += yorg;
prect++;
}
}
prect = prectInit;
numRects = REGION_NUM_RECTS(prgnClip) * nrectFill;
if (numRects > NUM_STACK_RECTS)
{
pboxClippedBase = (BoxPtr)xalloc(numRects * sizeof(BoxRec));
if (!pboxClippedBase)
return;
}
else
pboxClippedBase = stackRects;
pboxClipped = pboxClippedBase;
if (REGION_NUM_RECTS(prgnClip) == 1)
{
int x1, y1, x2, y2, bx2, by2;
pextent = REGION_RECTS(prgnClip);
x1 = pextent->x1;
y1 = pextent->y1;
x2 = pextent->x2;
y2 = pextent->y2;
while (nrectFill--)
{
if ((pboxClipped->x1 = prect->x) < x1)
pboxClipped->x1 = x1;
if ((pboxClipped->y1 = prect->y) < y1)
pboxClipped->y1 = y1;
bx2 = (int) prect->x + (int) prect->width;
if (bx2 > x2)
bx2 = x2;
pboxClipped->x2 = bx2;
by2 = (int) prect->y + (int) prect->height;
if (by2 > y2)
by2 = y2;
pboxClipped->y2 = by2;
prect++;
if ((pboxClipped->x1 < pboxClipped->x2) &&
(pboxClipped->y1 < pboxClipped->y2))
{
pboxClipped++;
}
}
}
else
{
int x1, y1, x2, y2, bx2, by2;
pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
x1 = pextent->x1;
y1 = pextent->y1;
x2 = pextent->x2;
y2 = pextent->y2;
while (nrectFill--)
{
BoxRec box;
if ((box.x1 = prect->x) < x1)
box.x1 = x1;
if ((box.y1 = prect->y) < y1)
box.y1 = y1;
bx2 = (int) prect->x + (int) prect->width;
if (bx2 > x2)
bx2 = x2;
box.x2 = bx2;
by2 = (int) prect->y + (int) prect->height;
if (by2 > y2)
by2 = y2;
box.y2 = by2;
prect++;
if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
continue;
n = REGION_NUM_RECTS (prgnClip);
pbox = REGION_RECTS(prgnClip);
/* clip the rectangle to each box in the clip region
this is logically equivalent to calling Intersect()
*/
while(n--)
{
pboxClipped->x1 = max(box.x1, pbox->x1);
pboxClipped->y1 = max(box.y1, pbox->y1);
pboxClipped->x2 = min(box.x2, pbox->x2);
pboxClipped->y2 = min(box.y2, pbox->y2);
pbox++;
/* see if clipping left anything */
if(pboxClipped->x1 < pboxClipped->x2 &&
pboxClipped->y1 < pboxClipped->y2)
{
pboxClipped++;
}
}
}
}
if (pboxClipped != pboxClippedBase)
{
switch (pGC->fillStyle) {
case FillSolid:
igsFillBoxSolid(pDrawable,
pboxClipped-pboxClippedBase, pboxClippedBase,
pGC->fgPixel, pGC->alu, pGC->planemask);
break;
case FillTiled:
igsFillBoxTiled(pDrawable,
pboxClipped-pboxClippedBase, pboxClippedBase,
pGC->tile.pixmap,
pGC->patOrg.x + pDrawable->x,
pGC->patOrg.y + pDrawable->y,
pGC->alu);
break;
case FillStippled:
case FillOpaqueStippled:
igsFillBoxStippled (pDrawable, pGC,
pboxClipped-pboxClippedBase, pboxClippedBase);
break;
}
}
if (pboxClippedBase != stackRects)
xfree(pboxClippedBase);
}
int
igsTextInRegion (GCPtr pGC,
int x,
int y,
unsigned int nglyph,
CharInfoPtr *ppci)
{
int w;
FontPtr pfont = pGC->font;
BoxRec bbox;
if (FONTCONSTMETRICS(pfont))
w = FONTMAXBOUNDS(pfont,characterWidth) * nglyph;
else
{
w = 0;
while (nglyph--)
w += (*ppci++)->metrics.characterWidth;
}
if (w < 0)
{
bbox.x1 = x + w;
bbox.x2 = x;
}
else
{
bbox.x1 = x;
bbox.x2 = x + w;
}
w = FONTMINBOUNDS(pfont,leftSideBearing);
if (w < 0)
bbox.x1 += w;
w = FONTMAXBOUNDS(pfont, rightSideBearing) - FONTMINBOUNDS(pfont, characterWidth);
if (w > 0)
bbox.x2 += w;
bbox.y1 = y - FONTMAXBOUNDS(pfont,ascent);
bbox.y2 = y + FONTMAXBOUNDS(pfont,descent);
return RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox);
}
void
igsGlyphBltClipped (DrawablePtr pDrawable,
GCPtr pGC,
int x,
int y,
unsigned int nglyph,
CharInfoPtr *ppciInit,
Bool image)
{
SetupIgs(pDrawable->pScreen);
CARD32 cmd;
int h;
int w;
int xBack, yBack;
int hBack, wBack;
int lw;
FontPtr pfont = pGC->font;
CharInfoPtr pci;
unsigned long *bits;
BoxPtr extents;
BoxRec bbox;
CARD32 b;
CharInfoPtr *ppci;
FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
RegionPtr pClip = fbGetCompositeClip(pGC);
BoxPtr pBox;
int nbox;
int x1, y1, x2, y2;
unsigned char alu;
Bool set;
PixTransDeclare;
if (image)
{
xBack = x;
yBack = y - FONTASCENT(pGC->font);
wBack = 0;
hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
if (hBack)
{
h = nglyph;
ppci = ppciInit;
while (h--)
wBack += (*ppci++)->metrics.characterWidth;
}
if (wBack < 0)
{
xBack = xBack + wBack;
wBack = -wBack;
}
if (hBack < 0)
{
yBack = yBack + hBack;
hBack = -hBack;
}
alu = GXcopy;
if (wBack)
{
_igsSetSolidRect (cop, GXcopy, pGC->planemask, pGC->bgPixel, cmd);
for (nbox = REGION_NUM_RECTS (pClip),
pBox = REGION_RECTS (pClip);
nbox--;
pBox++)
{
x1 = xBack;
x2 = xBack + wBack;
y1 = yBack;
y2 = yBack + hBack;
if (x1 < pBox->x1) x1 = pBox->x1;
if (x2 > pBox->x2) x2 = pBox->x2;
if (y1 < pBox->y1) y1 = pBox->y1;
if (y2 > pBox->y2) y2 = pBox->y2;
if (x1 < x2 && y1 < y2)
{
_igsRect (cop, x1, y1, x2 - x1, y2 - y1, cmd);
}
}
KdMarkSync (pDrawable->pScreen);
}
}
else
{
wBack = 0;
alu = pGC->alu;
}
ppci = ppciInit;
set = FALSE;
while (nglyph--)
{
pci = *ppci++;
h = pci->metrics.ascent + pci->metrics.descent;
w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
x1 = x + pci->metrics.leftSideBearing;
y1 = y - pci->metrics.ascent;
bbox.x1 = x1;
bbox.y1 = y1;
bbox.x2 = x1 + w;
bbox.y2 = y1 + h;
switch (RECT_IN_REGION(pGC->pScreen, pClip, &bbox))
{
case rgnIN:
lw = h * ((w + 31) >> 5);
if (lw)
{
if (!set)
{
_igsSetTransparentPlaneBlt (cop, alu, pGC->planemask, pGC->fgPixel, cmd);
set = TRUE;
}
_igsPlaneBlt(cop,
x + pci->metrics.leftSideBearing,
y - pci->metrics.ascent,
w, h, cmd);
bits = (unsigned long *) pci->bits;
PixTransStart (lw);
while (lw--)
{
b = *bits++;
IgsAdjustBits32 (b);
PixTransStore(b);
}
KdMarkSync (pDrawable->pScreen);
}
break;
case rgnPART:
set = FALSE;
KdCheckSync (pDrawable->pScreen);
fbPutXYImage (pDrawable,
pClip,
fbPriv->fg,
fbPriv->bg,
fbPriv->pm,
alu,
FALSE,
x1, y1,
w, h,
(FbStip *) pci->bits,
(w + 31) >> 5,
0);
break;
case rgnOUT:
break;
}
x += pci->metrics.characterWidth;
}
}
void
igsGlyphBlt (DrawablePtr pDrawable,
GCPtr pGC,
int x,
int y,
unsigned int nglyph,
CharInfoPtr *ppciInit,
Bool image)
{
SetupIgs(pDrawable->pScreen);
CARD32 cmd;
int h;
int w;
int xBack, yBack;
int hBack, wBack;
int lw;
FontPtr pfont = pGC->font;
CharInfoPtr pci;
unsigned long *bits;
BoxPtr extents;
BoxRec bbox;
CARD32 b;
CharInfoPtr *ppci;
unsigned char alu;
PixTransDeclare;
/*
* Paint background for image text
*/
if (image)
{
xBack = x;
yBack = y - FONTASCENT(pGC->font);
wBack = 0;
hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
if (hBack)
{
h = nglyph;
ppci = ppciInit;
while (h--)
wBack += (*ppci++)->metrics.characterWidth;
}
if (wBack < 0)
{
xBack = xBack + wBack;
wBack = -wBack;
}
if (hBack < 0)
{
yBack = yBack + hBack;
hBack = -hBack;
}
alu = GXcopy;
if (wBack)
{
_igsSetSolidRect (cop, GXcopy, pGC->planemask, pGC->bgPixel, cmd);
_igsRect (cop, xBack, yBack, wBack, hBack, cmd);
}
}
else
{
wBack = 0;
alu = pGC->alu;
}
_igsSetTransparentPlaneBlt (cop, alu, pGC->planemask, pGC->fgPixel, cmd);
ppci = ppciInit;
while (nglyph--)
{
pci = *ppci++;
h = pci->metrics.ascent + pci->metrics.descent;
w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
lw = h * ((w + 31) >> 5);
if (lw)
{
_igsPlaneBlt(cop,
x + pci->metrics.leftSideBearing,
y - pci->metrics.ascent,
w, h, cmd);
bits = (unsigned long *) pci->bits;
PixTransStart(lw);
while (lw--)
{
b = *bits++;
IgsAdjustBits32 (b);
PixTransStore(b);
}
}
x += pci->metrics.characterWidth;
}
KdMarkSync (pDrawable->pScreen);
}
void
igsTEGlyphBlt (DrawablePtr pDrawable,
GCPtr pGC,
int xInit,
int yInit,
unsigned int nglyph,
CharInfoPtr *ppci,
Bool image)
{
SetupIgs(pDrawable->pScreen);
CARD32 cmd;
int x, y;
int h, lw, lwTmp;
int w;
FontPtr pfont = pGC->font;
unsigned long *char1, *char2, *char3, *char4;
int widthGlyphs, widthGlyph;
BoxRec bbox;
CARD32 tmp;
PixTransDeclare;
widthGlyph = FONTMAXBOUNDS(pfont,characterWidth);
if (!widthGlyph)
return;
h = FONTASCENT(pfont) + FONTDESCENT(pfont);
if (!h)
return;
x = xInit + FONTMAXBOUNDS(pfont,leftSideBearing);
y = yInit - FONTASCENT(pfont);
if (image)
{
_igsSetOpaquePlaneBlt (cop, GXcopy, pGC->planemask, pGC->fgPixel, pGC->bgPixel, cmd);
}
else
{
_igsSetTransparentPlaneBlt (cop, pGC->alu, pGC->planemask, pGC->fgPixel, cmd);
}
#if BITMAP_BIT_ORDER == LSBFirst
#define SHIFT <<
#else
#define SHIFT >>
#endif
#define LoopIt(count, w, loadup, fetch) \
while (nglyph >= count) \
{ \
nglyph -= count; \
_igsPlaneBlt (cop, x, y, w, h, cmd); \
x += w; \
loadup \
lwTmp = h; \
PixTransStart(h); \
while (lwTmp--) { \
tmp = fetch; \
IgsAdjustBits32(tmp); \
PixTransStore(tmp); \
} \
}
if (widthGlyph <= 8)
{
widthGlyphs = widthGlyph << 2;
LoopIt(4, widthGlyphs,
char1 = (unsigned long *) (*ppci++)->bits;
char2 = (unsigned long *) (*ppci++)->bits;
char3 = (unsigned long *) (*ppci++)->bits;
char4 = (unsigned long *) (*ppci++)->bits;,
(*char1++ | ((*char2++ | ((*char3++ | (*char4++
SHIFT widthGlyph))
SHIFT widthGlyph))
SHIFT widthGlyph)))
}
else if (widthGlyph <= 10)
{
widthGlyphs = (widthGlyph << 1) + widthGlyph;
LoopIt(3, widthGlyphs,
char1 = (unsigned long *) (*ppci++)->bits;
char2 = (unsigned long *) (*ppci++)->bits;
char3 = (unsigned long *) (*ppci++)->bits;,
(*char1++ | ((*char2++ | (*char3++ SHIFT widthGlyph)) SHIFT widthGlyph)))
}
else if (widthGlyph <= 16)
{
widthGlyphs = widthGlyph << 1;
LoopIt(2, widthGlyphs,
char1 = (unsigned long *) (*ppci++)->bits;
char2 = (unsigned long *) (*ppci++)->bits;,
(*char1++ | (*char2++ SHIFT widthGlyph)))
}
lw = h * ((widthGlyph + 31) >> 5);
while (nglyph--)
{
_igsPlaneBlt (cop, x, y, widthGlyph, h, cmd);
x += widthGlyph;
char1 = (unsigned long *) (*ppci++)->bits;
lwTmp = lw;
PixTransStart(lw);
while (lwTmp--)
{
tmp = *char1++;
IgsAdjustBits32(tmp);
PixTransStore(tmp);
}
}
KdMarkSync (pDrawable->pScreen);
}
/*
* Blt glyphs using image transfer window
*/
void
igsPolyGlyphBlt (DrawablePtr pDrawable,
GCPtr pGC,
int x,
int y,
unsigned int nglyph,
CharInfoPtr *ppci,
pointer pglyphBase)
{
if (pGC->fillStyle != FillSolid ||
fbGetGCPrivate(pGC)->pm != FB_ALLONES)
{
KdCheckPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
return;
}
x += pDrawable->x;
y += pDrawable->y;
switch (igsTextInRegion (pGC, x, y, nglyph, ppci)) {
case rgnIN:
if (TERMINALFONT(pGC->font))
igsTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, FALSE);
else
igsGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, FALSE);
break;
case rgnPART:
igsGlyphBltClipped (pDrawable, pGC, x, y, nglyph, ppci, FALSE);
break;
case rgnOUT:
break;
}
}
void
igsImageGlyphBlt (DrawablePtr pDrawable,
GCPtr pGC,
int x, int y,
unsigned int nglyph,
CharInfoPtr *ppci,
pointer pglyphBase)
{
if (fbGetGCPrivate(pGC)->pm != FB_ALLONES)
{
KdCheckImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
return;
}
x += pDrawable->x;
y += pDrawable->y;
switch (igsTextInRegion (pGC, x, y, nglyph, ppci)) {
case rgnIN:
if (TERMINALFONT(pGC->font))
igsTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, TRUE);
else
igsGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, TRUE);
break;
case rgnPART:
igsGlyphBltClipped (pDrawable, pGC, x, y, nglyph, ppci, TRUE);
break;
case rgnOUT:
break;
}
}
static void
igsInvalidatePattern (IgsPatternCache *c,
PixmapPtr pPixmap)
{
int i;
if (c->base)
{
for (i = 0; i < IGS_NUM_PATTERN; i++)
{
if (c->pattern[i].serial_number == pPixmap->drawable.serialNumber)
c->pattern[i].serial_number = ~0;
}
}
}
static void
igsInitPattern (IgsPatternCache *c, int bsize, int psize)
{
int i;
int boffset;
int poffset;
for (i = 0; i < IGS_NUM_PATTERN; i++)
{
boffset = i * bsize;
poffset = i * psize;
c->pattern[i].xrot = -1;
c->pattern[i].yrot = -1;
c->pattern[i].serial_number = ~0;
c->pattern[i].offset = c->offset + poffset;
c->pattern[i].base = c->base + boffset;
}
c->next = 0;
}
static const GCOps igsOps = {
igsFillSpans,
KdCheckSetSpans,
KdCheckPutImage,
igsCopyArea,
igsCopyPlane,
KdCheckPolyPoint,
KdCheckPolylines,
KdCheckPolySegment,
miPolyRectangle,
KdCheckPolyArc,
miFillPolygon,
igsPolyFillRect,
KdCheckPolyFillArc,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
igsImageGlyphBlt,
igsPolyGlyphBlt,
igsPushPixels,
#ifdef NEED_LINEHELPER
,NULL
#endif
};
void
igsValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
{
FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC);
fbValidateGC (pGC, changes, pDrawable);
if (pDrawable->type == DRAWABLE_WINDOW)
pGC->ops = (GCOps *) &igsOps;
else
pGC->ops = (GCOps *) &fbGCOps;
}
GCFuncs igsGCFuncs = {
igsValidateGC,
miChangeGC,
miCopyGC,
miDestroyGC,
miChangeClip,
miDestroyClip,
miCopyClip
};
int
igsCreateGC (GCPtr pGC)
{
if (!fbCreateGC (pGC))
return FALSE;
if (pGC->depth != 1)
pGC->funcs = &igsGCFuncs;
return TRUE;
}
void
igsCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
KdScreenPriv(pScreen);
RegionRec rgnDst;
int dx, dy;
WindowPtr pwinRoot;
pwinRoot = WindowTable[pWin->drawable.pScreen->myNum];
dx = ptOldOrg.x - pWin->drawable.x;
dy = ptOldOrg.y - pWin->drawable.y;
REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot,
0,
&rgnDst, dx, dy, igsCopyNtoN, 0, 0);
REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
}
void
igsPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
{
KdScreenPriv(pWin->drawable.pScreen);
PixmapPtr pTile;
if (!REGION_NUM_RECTS(pRegion))
return;
switch (what) {
case PW_BACKGROUND:
switch (pWin->backgroundState) {
case None:
return;
case ParentRelative:
do {
pWin = pWin->parent;
} while (pWin->backgroundState == ParentRelative);
(*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
what);
return;
case BackgroundPixmap:
pTile = pWin->background.pixmap;
if (igsPatternDimOk (pTile->drawable.width) &&
igsPatternDimOk (pTile->drawable.height))
{
igsFillBoxTiled ((DrawablePtr)pWin,
(int)REGION_NUM_RECTS(pRegion),
REGION_RECTS(pRegion),
pTile,
pWin->drawable.x, pWin->drawable.y, GXcopy);
return;
}
break;
case BackgroundPixel:
igsFillBoxSolid((DrawablePtr)pWin,
(int)REGION_NUM_RECTS(pRegion),
REGION_RECTS(pRegion),
pWin->background.pixel, GXcopy, ~0);
return;
}
break;
case PW_BORDER:
if (pWin->borderIsPixel)
{
igsFillBoxSolid((DrawablePtr)pWin,
(int)REGION_NUM_RECTS(pRegion),
REGION_RECTS(pRegion),
pWin->border.pixel, GXcopy, ~0);
return;
}
else
{
pTile = pWin->border.pixmap;
if (igsPatternDimOk (pTile->drawable.width) &&
igsPatternDimOk (pTile->drawable.height))
{
igsFillBoxTiled ((DrawablePtr)pWin,
(int)REGION_NUM_RECTS(pRegion),
REGION_RECTS(pRegion),
pTile,
pWin->drawable.x, pWin->drawable.y, GXcopy);
return;
}
}
break;
}
KdCheckPaintWindow (pWin, pRegion, what);
}
Bool
igsDrawInit (ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
igsCardInfo(pScreenPriv);
igsScreenInfo(pScreenPriv);
int i;
int pattern_size;
int boffset, poffset;
KdScreenInitAsync (pScreen);
/*
* Replace various fb screen functions
*/
pScreen->CreateGC = igsCreateGC;
pScreen->CopyWindow = igsCopyWindow;
pScreen->PaintWindowBackground = igsPaintWindow;
pScreen->PaintWindowBorder = igsPaintWindow;
/*
* Initialize patterns
*/
if (igss->tile.base)
{
pattern_size = IgsTileSize(pScreenPriv->screen->fb[0].bitsPerPixel);
igsInitPattern (&igss->tile,
pattern_size,
pattern_size * 8 / pScreenPriv->screen->fb[0].bitsPerPixel);
pattern_size = IgsStippleSize(pScreenPriv->screen->fb[0].bitsPerPixel);
igsInitPattern (&igss->stipple,
pattern_size,
pattern_size * 8 / pScreenPriv->screen->fb[0].bitsPerPixel);
}
return TRUE;
}
void
igsDrawEnable (ScreenPtr pScreen)
{
SetupIgs(pScreen);
CARD32 cmd;
CARD32 base;
CARD16 stride;
CARD32 format;
stride = pScreenPriv->screen->fb[0].pixelStride;
_igsWaitIdleEmpty(cop);
_igsReset(cop);
switch (pScreenPriv->screen->fb[0].bitsPerPixel) {
case 8:
format = IGS_FORMAT_8BPP;
break;
case 16:
format = IGS_FORMAT_16BPP;
break;
case 24:
format = IGS_FORMAT_24BPP;
break;
case 32:
format = IGS_FORMAT_32BPP;
break;
}
cop->format = format;
cop->dst_stride = stride - 1;
cop->src1_stride = stride - 1;
cop->src2_stride = stride - 1;
cop->src1_start = 0;
cop->src2_start = 0;
cop->extension |= IGS_BLOCK_COP_REG | IGS_BURST_ENABLE;
_igsSetSolidRect(cop, GXcopy, ~0, pScreen->blackPixel, cmd);
_igsRect (cop, 0, 0,
pScreenPriv->screen->width, pScreenPriv->screen->height,
cmd);
_igsWaitIdleEmpty (cop);
}
void
igsDrawDisable (ScreenPtr pScreen)
{
}
void
igsDrawFini (ScreenPtr pScreen)
{
}
void
igsDrawSync (ScreenPtr pScreen)
{
SetupIgs(pScreen);
_igsWaitIdleEmpty(cop);
}