#include "ffb.h"
#include "ffb_regs.h"
#include "ffb_rcache.h"
#include "ffb_fifo.h"
#include "ffb_loops.h"
#include "ffb_gc.h"
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "fontstruct.h"
#include "dixfontstr.h"
#define PSZ 8
#include "cfb.h"
#undef PSZ
#include "cfb32.h"
#include "migc.h"
#include "mi.h"
#include "mispans.h"
GCOps CreatorTEOps1Rect8 = {
CreatorFillSpans,
CreatorSetSpans,
cfbPutImage,
CreatorCopyArea,
CreatorCopyPlane,
CreatorPolyPoint,
CreatorPolylines,
CreatorPolySegment,
miPolyRectangle,
CreatorZeroPolyArc,
CreatorFillPolygon,
CreatorPolyFillRect,
CreatorPolyFillArcSolid,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
CreatorTEGlyphBlt,
CreatorPolyTEGlyphBlt,
miPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps CreatorTEOps1Rect32 = {
CreatorFillSpans,
CreatorSetSpans,
cfb32PutImage,
CreatorCopyArea,
CreatorCopyPlane,
CreatorPolyPoint,
CreatorPolylines,
CreatorPolySegment,
miPolyRectangle,
CreatorZeroPolyArc,
CreatorFillPolygon,
CreatorPolyFillRect,
CreatorPolyFillArcSolid,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
CreatorTEGlyphBlt,
CreatorPolyTEGlyphBlt,
miPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps CreatorTEOps8 = {
CreatorFillSpans,
CreatorSetSpans,
cfbPutImage,
CreatorCopyArea,
CreatorCopyPlane,
CreatorPolyPoint,
CreatorLineSSStub,
CreatorSegmentSSStub,
miPolyRectangle,
CreatorZeroPolyArc,
CreatorFillPolygon,
CreatorPolyFillRect,
CreatorPolyFillArcSolid,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
CreatorTEGlyphBlt,
CreatorPolyTEGlyphBlt,
miPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps CreatorTEOps32 = {
CreatorFillSpans,
CreatorSetSpans,
cfb32PutImage,
CreatorCopyArea,
CreatorCopyPlane,
CreatorPolyPoint,
CreatorLineSSStub,
CreatorSegmentSSStub,
miPolyRectangle,
CreatorZeroPolyArc,
CreatorFillPolygon,
CreatorPolyFillRect,
CreatorPolyFillArcSolid,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
CreatorTEGlyphBlt,
CreatorPolyTEGlyphBlt,
miPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps CreatorNonTEOps1Rect8 = {
CreatorFillSpans,
CreatorSetSpans,
cfbPutImage,
CreatorCopyArea,
CreatorCopyPlane,
CreatorPolyPoint,
CreatorPolylines,
CreatorPolySegment,
miPolyRectangle,
CreatorZeroPolyArc,
CreatorFillPolygon,
CreatorPolyFillRect,
CreatorPolyFillArcSolid,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
miImageGlyphBlt,
CreatorPolyGlyphBlt,
miPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps CreatorNonTEOps1Rect32 = {
CreatorFillSpans,
CreatorSetSpans,
cfb32PutImage,
CreatorCopyArea,
CreatorCopyPlane,
CreatorPolyPoint,
CreatorPolylines,
CreatorPolySegment,
miPolyRectangle,
CreatorZeroPolyArc,
CreatorFillPolygon,
CreatorPolyFillRect,
CreatorPolyFillArcSolid,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
miImageGlyphBlt,
CreatorPolyGlyphBlt,
miPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps CreatorNonTEOps8 = {
CreatorFillSpans,
CreatorSetSpans,
cfbPutImage,
CreatorCopyArea,
CreatorCopyPlane,
CreatorPolyPoint,
CreatorLineSSStub,
CreatorSegmentSSStub,
miPolyRectangle,
CreatorZeroPolyArc,
CreatorFillPolygon,
CreatorPolyFillRect,
CreatorPolyFillArcSolid,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
miImageGlyphBlt,
CreatorPolyGlyphBlt,
miPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
GCOps CreatorNonTEOps32 = {
CreatorFillSpans,
CreatorSetSpans,
cfb32PutImage,
CreatorCopyArea,
CreatorCopyPlane,
CreatorPolyPoint,
CreatorLineSSStub,
CreatorSegmentSSStub,
miPolyRectangle,
CreatorZeroPolyArc,
CreatorFillPolygon,
CreatorPolyFillRect,
CreatorPolyFillArcSolid,
miPolyText8,
miPolyText16,
miImageText8,
miImageText16,
miImageGlyphBlt,
CreatorPolyGlyphBlt,
miPushPixels
#ifdef NEED_LINEHELPER
,NULL
#endif
};
#define FONTWIDTH(font) (FONTMAXBOUNDS(font,rightSideBearing) - \
FONTMINBOUNDS(font,leftSideBearing))
#define FONTHEIGHT(font) (FONTMAXBOUNDS(font,ascent) + \
FONTMINBOUNDS(font,descent))
static GCOps *
CreatorMatchCommon (GCPtr pGC, cfbPrivGCPtr devPriv)
{
int depth = pGC->depth;
if (pGC->lineWidth != 0) return 0;
if (pGC->lineStyle != LineSolid) return 0;
if (pGC->fillStyle != FillSolid) return 0;
if (devPriv->rop != GXcopy) return 0;
if (pGC->font &&
FONTWIDTH (pGC->font) <= 32 &&
FONTHEIGHT (pGC->font) <= 100 &&
FONTMINBOUNDS(pGC->font,characterWidth) >= 0) {
if (TERMINALFONT(pGC->font)) {
if (devPriv->oneRect) {
return (depth == 8 ?
&CreatorTEOps1Rect8 :
&CreatorTEOps1Rect32);
} else {
return (depth == 8 ?
&CreatorTEOps8 :
&CreatorTEOps32);
}
} else {
if (devPriv->oneRect) {
return (depth == 8 ?
&CreatorNonTEOps1Rect8 :
&CreatorNonTEOps1Rect32);
} else {
return (depth == 8 ?
&CreatorNonTEOps8 :
&CreatorNonTEOps32);
}
}
}
return 0;
}
static void
CreatorDestroyGC (GCPtr pGC)
{
CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
if (gcPriv->stipple)
xfree (gcPriv->stipple);
miDestroyGC (pGC);
}
static __inline__ void
CreatorNewLine(GCPtr pGC, cfbPrivGCPtr devPriv, CreatorPrivGCPtr gcPriv, int accel)
{
pGC->ops->FillPolygon = miFillPolygon;
pGC->ops->PolyRectangle = miPolyRectangle;
if (pGC->lineWidth == 0)
pGC->ops->PolyArc = miZeroPolyArc;
else
pGC->ops->PolyArc = miPolyArc;
if (accel) {
pGC->ops->FillPolygon = CreatorFillPolygon;
if (pGC->lineWidth == 0 && pGC->capStyle != CapNotLast)
pGC->ops->PolyArc = CreatorZeroPolyArc;
}
pGC->ops->PolySegment = miPolySegment;
gcPriv->linepat = 0;
if (accel && !devPriv->oneRect)
accel = 0;
if (pGC->lineStyle == LineSolid) {
if(pGC->lineWidth == 0) {
if (pGC->fillStyle == FillSolid) {
pGC->ops->Polylines = CreatorLineSSStub;
pGC->ops->PolySegment = CreatorSegmentSSStub;
} else
pGC->ops->Polylines = miZeroLine;
if (accel) {
gcPriv->PolySegment = pGC->ops->PolySegment;
gcPriv->Polylines = pGC->ops->Polylines;
pGC->ops->PolySegment = CreatorPolySegment;
pGC->ops->Polylines = CreatorPolylines;
}
} else {
pGC->ops->Polylines = miWideLine;
}
} else if(pGC->lineStyle == LineOnOffDash) {
if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) {
pGC->ops->Polylines = CreatorLineSDStub;
pGC->ops->PolySegment = CreatorSegmentSDStub;
if(accel &&
CreatorCheckLinePattern(pGC, gcPriv)) {
gcPriv->PolySegment = pGC->ops->PolySegment;
gcPriv->Polylines = pGC->ops->Polylines;
pGC->ops->PolySegment = CreatorPolySegment;
pGC->ops->Polylines = CreatorPolylines;
}
} else {
pGC->ops->Polylines = miWideDash;
}
} else if(pGC->lineStyle == LineDoubleDash) {
if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) {
pGC->ops->Polylines = CreatorLineSDStub;
pGC->ops->PolySegment = CreatorSegmentSDStub;
} else {
pGC->ops->Polylines = miWideDash;
}
}
}
static __inline__ void
CreatorNewGlyph(GCPtr pGC, CreatorPrivGCPtr gcPriv)
{
if (FONTWIDTH(pGC->font) > 32 ||
FONTHEIGHT(pGC->font) > 100 ||
FONTMINBOUNDS(pGC->font,characterWidth) < 0) {
pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
} else {
if (pGC->fillStyle == FillSolid) {
if (TERMINALFONT (pGC->font)) {
pGC->ops->PolyGlyphBlt = CreatorPolyTEGlyphBlt;
} else {
pGC->ops->PolyGlyphBlt = CreatorPolyGlyphBlt;
}
} else {
pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
}
if (TERMINALFONT(pGC->font))
pGC->ops->ImageGlyphBlt = CreatorTEGlyphBlt;
else
pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
}
}
static __inline__ void
CreatorNewFillSpans(GCPtr pGC, cfbPrivGCPtr devPriv, CreatorPrivGCPtr gcPriv, int accel)
{
if (pGC->fillStyle == FillSolid) {
pGC->ops->FillSpans = CreatorSolidSpansGeneralStub;
} else if(pGC->fillStyle == FillTiled) {
if (pGC->pRotatedPixmap) {
int pmsk = (pGC->depth == 8 ? 0xff : 0xffffff);
if (pGC->alu == GXcopy && (pGC->planemask & pmsk) == pmsk)
pGC->ops->FillSpans = CreatorTile32FSCopyStub;
else
pGC->ops->FillSpans = CreatorTile32FSGeneralStub;
} else
pGC->ops->FillSpans = CreatorUnnaturalTileFSStub;
} else if(pGC->fillStyle == FillStippled) {
if (pGC->pRotatedPixmap)
pGC->ops->FillSpans = Creator8Stipple32FSStub;
else
pGC->ops->FillSpans = CreatorUnnaturalStippleFSStub;
} else if(pGC->fillStyle == FillOpaqueStippled) {
if (pGC->pRotatedPixmap)
pGC->ops->FillSpans = Creator8OpaqueStipple32FSStub;
else
pGC->ops->FillSpans = CreatorUnnaturalStippleFSStub;
} else
FatalError("CreatorValidateGC: illegal fillStyle\n");
if (accel)
pGC->ops->FillSpans = CreatorFillSpans;
}
static __inline__ void
CreatorNewFillArea(GCPtr pGC, cfbPrivGCPtr devPriv, CreatorPrivGCPtr gcPriv, int accel)
{
if (accel) {
pGC->ops->PolyFillRect = CreatorPolyFillRect;
pGC->ops->PolyFillArc = CreatorPolyFillArcSolid;
} else {
pGC->ops->PolyFillRect = miPolyFillRect;
if(pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled)
pGC->ops->PolyFillRect = CreatorPolyFillRectStub;
pGC->ops->PolyFillArc = miPolyFillArc;
}
pGC->ops->PushPixels = mfbPushPixels;
}
void
CreatorValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
{
int mask;
int new_rrop;
int new_line, new_text, new_fillspans, new_fillarea;
int new_rotate;
int xrot, yrot;
cfbPrivGCPtr devPriv;
CreatorPrivGCPtr gcPriv;
int oneRect, type;
int accel, drawableChanged;
FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
gcPriv = CreatorGetGCPrivate (pGC);
type = pFfb->vtSema ? -1 : pDrawable->type;
if (type != DRAWABLE_WINDOW) {
if (gcPriv->type == DRAWABLE_WINDOW) {
extern GCOps cfbNonTEOps;
extern GCOps cfb32NonTEOps;
miDestroyGCOps (pGC->ops);
if (pGC->depth == 8)
pGC->ops = &cfbNonTEOps;
else
pGC->ops = &cfb32NonTEOps;
changes = (1 << (GCLastBit+1)) - 1;
pGC->stateChanges = changes;
gcPriv->type = type;
}
if (pGC->depth == 8)
cfbValidateGC (pGC, changes, pDrawable);
else
cfb32ValidateGC (pGC, changes, pDrawable);
if (!pGC->ops->devPrivate.val) {
pGC->ops = miCreateGCOps(pGC->ops);
pGC->ops->devPrivate.val = 1;
}
pGC->ops->CopyArea = CreatorCopyArea;
return;
}
if (gcPriv->type != DRAWABLE_WINDOW) {
changes = (1 << (GCLastBit+1)) - 1;
gcPriv->type = DRAWABLE_WINDOW;
}
new_rotate = pGC->lastWinOrg.x != pDrawable->x ||
pGC->lastWinOrg.y != pDrawable->y;
if(new_rotate != 0) {
pGC->lastWinOrg.x = pDrawable->x;
pGC->lastWinOrg.y = pDrawable->y;
}
devPriv = cfbGetGCPrivate(pGC);
new_rrop = FALSE;
new_line = FALSE;
new_text = FALSE;
new_fillspans = FALSE;
new_fillarea = FALSE;
drawableChanged = (pDrawable->serialNumber !=
(pGC->serialNumber & (DRAWABLE_SERIAL_BITS)));
#define CLIP_BITS (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)
if ((changes & CLIP_BITS) != 0 || drawableChanged) {
miComputeCompositeClip(pGC, pDrawable);
oneRect = REGION_NUM_RECTS(cfbGetCompositeClip(pGC)) == 1;
if (oneRect != devPriv->oneRect) {
new_line = TRUE;
devPriv->oneRect = oneRect;
}
}
mask = changes;
if((mask & (GCFunction | GCForeground | GCBackground | GCPlaneMask)) != 0)
new_rrop = TRUE;
if((mask & (GCPlaneMask | GCFillStyle | GCFont)) != 0)
new_text = TRUE;
if((mask & (GCLineStyle | GCLineWidth | GCFillStyle | GCCapStyle)) != 0)
new_line = TRUE;
if((mask & (GCFillStyle | GCTile | GCStipple)) != 0)
new_fillspans = new_fillarea = TRUE;
if(new_rotate == FALSE &&
(mask & (GCTileStipXOrigin | GCTileStipYOrigin)) != 0)
new_rotate = TRUE;
if((mask & GCStipple) != 0) {
if(pGC->stipple) {
int width = pGC->stipple->drawable.width;
PixmapPtr nstipple;
if ((width <= 32) && !(width & (width - 1))) {
int depth = pGC->depth;
nstipple = (depth == 8 ?
cfbCopyPixmap(pGC->stipple) :
cfb32CopyPixmap(pGC->stipple));
if (nstipple) {
if (depth == 8)
cfbPadPixmap(nstipple);
else
cfb32PadPixmap(nstipple);
(*pGC->pScreen->DestroyPixmap)(pGC->stipple);
pGC->stipple = nstipple;
}
}
}
}
if (drawableChanged)
new_fillspans = TRUE;
if (new_rotate || new_fillspans) {
Bool new_pix = FALSE;
xrot = pGC->patOrg.x + pDrawable->x;
yrot = pGC->patOrg.y + pDrawable->y;
if (!CreatorCheckFill (pGC, pDrawable)) {
switch (pGC->fillStyle) {
case FillTiled:
if (!pGC->tileIsPixel)
{
int width = pGC->tile.pixmap->drawable.width;
if (pGC->depth == 8)
width *= 8;
else
width *= 32;
if ((width <= 32) && !(width & (width - 1))) {
if (pGC->depth == 8)
cfbCopyRotatePixmap(pGC->tile.pixmap,
&pGC->pRotatedPixmap,
xrot, yrot);
else
cfb32CopyRotatePixmap(pGC->tile.pixmap,
&pGC->pRotatedPixmap,
xrot, yrot);
new_pix = TRUE;
}
}
break;
case FillStippled:
case FillOpaqueStippled:
{
int width = pGC->stipple->drawable.width;
if ((width <= 32) && !(width & (width - 1)))
{
mfbCopyRotatePixmap(pGC->stipple,
&pGC->pRotatedPixmap, xrot, yrot);
new_pix = TRUE;
}
}
break;
}
}
if (!new_pix && pGC->pRotatedPixmap) {
(*pGC->pScreen->DestroyPixmap)(pGC->pRotatedPixmap);
pGC->pRotatedPixmap = (PixmapPtr) NULL;
}
}
if (new_rrop) {
int old_rrop;
if (gcPriv->stipple) {
if (pGC->fillStyle == FillStippled)
gcPriv->stipple->alu = pGC->alu | FFB_ROP_EDIT_BIT;
else
gcPriv->stipple->alu = pGC->alu;
if (pGC->fillStyle != FillTiled) {
gcPriv->stipple->fg = pGC->fgPixel;
gcPriv->stipple->bg = pGC->bgPixel;
}
}
old_rrop = devPriv->rop;
if (pGC->depth == 8)
devPriv->rop = cfbReduceRasterOp (pGC->alu, pGC->fgPixel,
pGC->planemask,
&devPriv->and, &devPriv->xor);
else
devPriv->rop = cfb32ReduceRasterOp (pGC->alu, pGC->fgPixel,
pGC->planemask,
&devPriv->and, &devPriv->xor);
if (old_rrop == devPriv->rop)
new_rrop = FALSE;
else {
new_line = TRUE;
new_text = TRUE;
new_fillspans = TRUE;
new_fillarea = TRUE;
}
}
if (new_rrop || new_fillspans || new_text || new_fillarea || new_line) {
GCOps *newops;
int using_creator_ops = 0;
if ((newops = CreatorMatchCommon (pGC, devPriv))) {
if (pGC->ops->devPrivate.val)
miDestroyGCOps (pGC->ops);
pGC->ops = newops;
new_rrop = new_line = new_fillspans = new_text = new_fillarea = 0;
using_creator_ops = 1;
} else {
if (!pGC->ops->devPrivate.val) {
pGC->ops = miCreateGCOps (pGC->ops);
pGC->ops->devPrivate.val = 1;
}
pGC->ops->CopyArea = CreatorCopyArea;
}
if (pGC->depth == 8)
newops = cfbMatchCommon(pGC, devPriv);
else
newops = cfb32MatchCommon(pGC, devPriv);
if (newops) {
gcPriv->PolySegment = newops->PolySegment;
gcPriv->Polylines = newops->Polylines;
if (using_creator_ops) {
if (pGC->ops->PolySegment == CreatorPolySegment)
gcPriv->PolySegment = CreatorSegmentSSStub;
if (pGC->ops->Polylines == CreatorPolylines)
gcPriv->Polylines = CreatorLineSSStub;
}
}
}
accel = pGC->fillStyle == FillSolid || gcPriv->stipple;
if (new_line)
CreatorNewLine(pGC, devPriv, gcPriv, accel);
if (new_text && pGC->font)
CreatorNewGlyph(pGC, gcPriv);
if (new_fillspans)
CreatorNewFillSpans(pGC, devPriv, gcPriv, accel);
if (new_fillarea)
CreatorNewFillArea(pGC, devPriv, gcPriv, accel);
}
GCFuncs CreatorGCFuncs = {
CreatorValidateGC,
miChangeGC,
miCopyGC,
CreatorDestroyGC,
miChangeClip,
miDestroyClip,
miCopyClip
};
Bool
CreatorCreateGC (GCPtr pGC)
{
CreatorPrivGCPtr gcPriv;
if (pGC->depth == 1)
return mfbCreateGC(pGC);
if (pGC->depth == 8) {
if (!cfbCreateGC(pGC))
return FALSE;
} else {
if (!cfb32CreateGC(pGC))
return FALSE;
}
if (pGC->depth == 8)
pGC->ops = &CreatorNonTEOps8;
else
pGC->ops = &CreatorNonTEOps32;
pGC->funcs = &CreatorGCFuncs;
gcPriv = CreatorGetGCPrivate(pGC);
gcPriv->type = DRAWABLE_WINDOW;
gcPriv->linepat = 0;
gcPriv->stipple = 0;
gcPriv->PolySegment = CreatorSegmentSSStub;
gcPriv->Polylines = CreatorLineSSStub;
return TRUE;
}