summaryrefslogtreecommitdiff
path: root/hw/kdrive/savage/s3gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/kdrive/savage/s3gc.c')
-rw-r--r--hw/kdrive/savage/s3gc.c388
1 files changed, 388 insertions, 0 deletions
diff --git a/hw/kdrive/savage/s3gc.c b/hw/kdrive/savage/s3gc.c
new file mode 100644
index 000000000..245dfc483
--- /dev/null
+++ b/hw/kdrive/savage/s3gc.c
@@ -0,0 +1,388 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+/* $XFree86: $ */
+
+#include "s3.h"
+#include "s3draw.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 "migc.h"
+
+/*
+ * Common op groups. Common assumptions:
+ *
+ * lineWidth 0
+ * lineStyle LineSolid
+ * fillStyle FillSolid
+ * rop GXcopy
+ * font <= 32 pixels wide
+ */
+
+/* TE font, >= 4 pixels wide, one clip rectangle */
+static GCOps s3TEOps1Rect = {
+ s3FillSpans,
+ fbSetSpans,
+ fbPutImage,
+ s3CopyArea,
+ s3CopyPlane,
+ fbPolyPoint,
+ s3Polylines,
+ s3PolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ s3FillPoly1Rect,
+ s3PolyFillRect,
+ s3PolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ s3ImageTEGlyphBlt,
+ s3PolyTEGlyphBlt,
+ fbPushPixels,
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+extern GCOps fbGCOps;
+
+/* Non TE font, one clip rectangle */
+static GCOps s3NonTEOps1Rect = {
+ s3FillSpans,
+ fbSetSpans,
+ fbPutImage,
+ s3CopyArea,
+ s3CopyPlane,
+ fbPolyPoint,
+ s3Polylines,
+ s3PolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ s3FillPoly1Rect,
+ s3PolyFillRect,
+ s3PolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ s3ImageGlyphBlt,
+ s3PolyGlyphBlt,
+ fbPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+/* TE font, != 1 clip rect (including 0) */
+static GCOps s3TEOps = {
+ s3FillSpans,
+ fbSetSpans,
+ fbPutImage,
+ s3CopyArea,
+ s3CopyPlane,
+ fbPolyPoint,
+ s3Polylines,
+ s3PolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ miFillPolygon,
+ s3PolyFillRect,
+ s3PolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ s3ImageTEGlyphBlt,
+ s3PolyTEGlyphBlt,
+ fbPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+/* Non TE font, != 1 clip rect (including 0) */
+static GCOps s3NonTEOps = {
+ s3FillSpans,
+ fbSetSpans,
+ fbPutImage,
+ s3CopyArea,
+ s3CopyPlane,
+ fbPolyPoint,
+ s3Polylines,
+ s3PolySegment,
+ miPolyRectangle,
+ fbPolyArc,
+ miFillPolygon,
+ s3PolyFillRect,
+ s3PolyFillArcSolid,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ s3ImageGlyphBlt,
+ s3PolyGlyphBlt,
+ fbPushPixels
+#ifdef NEED_LINEHELPER
+ ,NULL
+#endif
+};
+
+static GCOps *
+s3MatchCommon (DrawablePtr pDraw, GCPtr pGC, FbGCPrivPtr fbPriv)
+{
+ KdScreenPriv (pDraw->pScreen);
+
+ if (!REGION_NOTEMPTY(pDraw->pScreen,fbGetCompositeClip(pGC)))
+ {
+ DRAW_DEBUG ((DEBUG_CLIP, "Empty composite clip, clipping all ops"));
+ return &kdNoopOps;
+ }
+
+ if (pDraw->type != DRAWABLE_WINDOW)
+ return (GCOps *) &fbGCOps;
+
+ if (pGC->lineWidth != 0)
+ return 0;
+ if (pGC->lineStyle != LineSolid)
+ return 0;
+ if (pGC->fillStyle != FillSolid)
+ return 0;
+ if (fbPriv->and != 0)
+ return 0;
+ if (pGC->font)
+ {
+ if (TERMINALFONT(pGC->font))
+ {
+ if (fbPriv->oneRect)
+ return &s3TEOps1Rect;
+ else
+ return &s3TEOps;
+ }
+ else
+ {
+ if (fbPriv->oneRect)
+ return &s3NonTEOps1Rect;
+ else
+ return &s3NonTEOps;
+ }
+ }
+ return 0;
+}
+
+void
+s3ValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
+{
+ int new_type; /* drawable type has changed */
+ int new_onerect; /* onerect value has changed */
+ int new_origin;
+
+ /* flags for changing the proc vector */
+ FbGCPrivPtr fbPriv;
+ s3PrivGCPtr s3Priv;
+ int oneRect;
+
+ fbPriv = fbGetGCPrivate(pGC);
+ s3Priv = s3GetGCPrivate(pGC);
+
+ new_type = FALSE;
+ new_onerect = FALSE;
+ new_origin = FALSE;
+
+ /*
+ * If the type of drawable has changed, fix up accelerated functions
+ */
+ if (s3Priv->type != pDrawable->type)
+ {
+ new_type = TRUE;
+ s3Priv->type = pDrawable->type;
+ }
+
+ /*
+ * Check tile/stipple origin
+ */
+ if (pGC->lastWinOrg.x != pDrawable->x || pGC->lastWinOrg.y != pDrawable->y)
+ new_origin = TRUE;
+
+ /*
+ * Call down to FB to set clip list and rrop values
+ */
+ oneRect = fbPriv->oneRect;
+
+ fbValidateGC (pGC, changes, pDrawable);
+
+ if (oneRect != fbPriv->oneRect)
+ new_onerect = TRUE;
+
+ /*
+ * Check accelerated pattern if necessary
+ */
+ if (changes & (GCFillStyle|GCStipple|GCTile))
+ s3CheckGCFill (pGC);
+ else if (s3Priv->pPattern &&
+ (new_origin || changes & (GCTileStipXOrigin|GCTileStipYOrigin)))
+ s3MoveGCFill (pGC);
+
+ /*
+ * Try to match common vector
+ */
+
+ if (new_type || new_onerect ||
+ (changes & (GCLineWidth|GCLineStyle|GCFillStyle|
+ GCFont|GCForeground|GCFunction|GCPlaneMask)))
+ {
+ GCOps *newops;
+
+ if (newops = s3MatchCommon (pDrawable, pGC, fbPriv))
+ {
+ if (pGC->ops->devPrivate.val)
+ miDestroyGCOps (pGC->ops);
+ pGC->ops = newops;
+ return;
+ }
+ }
+
+ /*
+ * No common vector matched, create private ops vector and
+ * fill it in
+ */
+ if (!pGC->ops->devPrivate.val)
+ {
+ /*
+ * Switch from noop vector by first switching to fb
+ * vector and fixing it up
+ */
+ if (pGC->ops == &kdNoopOps)
+ {
+ pGC->ops = (GCOps *) &fbGCOps;
+ new_type = TRUE;
+ }
+ pGC->ops = miCreateGCOps (pGC->ops);
+ pGC->ops->devPrivate.val = 1;
+ }
+
+ /*
+ * Fills
+ */
+ if (new_type || (changes & (GCFillStyle|GCTile|GCStipple)))
+ {
+ pGC->ops->FillSpans = fbFillSpans;
+ pGC->ops->PolyFillRect = fbPolyFillRect;
+ if (s3Priv->type == DRAWABLE_WINDOW &&
+ (pGC->fillStyle != FillTiled || s3Priv->pPattern))
+ {
+ pGC->ops->FillSpans = s3FillSpans;
+ pGC->ops->PolyFillRect = s3PolyFillRect;
+ }
+ }
+
+ /*
+ * Blt
+ */
+ if (new_type)
+ {
+ pGC->ops->CopyArea = fbCopyArea;
+ pGC->ops->CopyPlane = fbCopyPlane;
+ if (s3Priv->type == DRAWABLE_WINDOW)
+ {
+ pGC->ops->CopyArea = s3CopyArea;
+ pGC->ops->CopyPlane = s3CopyPlane;
+ }
+ }
+
+ /*
+ * Lines
+ */
+ if (new_type || (changes & (GCLineStyle|GCLineWidth|GCFillStyle)))
+ {
+ pGC->ops->Polylines = fbPolyLine;
+ pGC->ops->PolySegment = fbPolySegment;
+ if (pGC->lineStyle == LineSolid &&
+ pGC->lineWidth == 0 &&
+ pGC->fillStyle == FillSolid &&
+ s3Priv->type == DRAWABLE_WINDOW)
+ {
+ pGC->ops->Polylines = s3Polylines;
+ pGC->ops->PolySegment = s3PolySegment;
+ }
+ }
+
+ /*
+ * Polygons
+ */
+ if (new_type || new_onerect || (changes & (GCFillStyle)))
+ {
+ pGC->ops->FillPolygon = miFillPolygon;
+ if (s3Priv->type == DRAWABLE_WINDOW &&
+ fbPriv->oneRect &&
+ pGC->fillStyle == FillSolid)
+ {
+ pGC->ops->FillPolygon = s3FillPoly1Rect;
+ }
+ }
+
+ /*
+ * Filled arcs
+ */
+ if (new_type || (changes & GCFillStyle))
+ {
+ pGC->ops->PolyFillArc = fbPolyFillArc;
+ if (s3Priv->type == DRAWABLE_WINDOW &&
+ pGC->fillStyle == FillSolid)
+ {
+ pGC->ops->PolyFillArc = s3PolyFillArcSolid;
+ }
+ }
+
+ /*
+ * Text
+ */
+ if (new_type || (changes & (GCFont|GCFillStyle)))
+ {
+ pGC->ops->PolyGlyphBlt = fbPolyGlyphBlt;
+ pGC->ops->ImageGlyphBlt = fbImageGlyphBlt;
+ if (s3Priv->type == DRAWABLE_WINDOW && pGC->font)
+ {
+ if (pGC->fillStyle == FillSolid)
+ {
+ if (TERMINALFONT(pGC->font))
+ pGC->ops->PolyGlyphBlt = s3PolyTEGlyphBlt;
+ else
+ pGC->ops->PolyGlyphBlt = s3PolyGlyphBlt;
+ }
+ if (TERMINALFONT(pGC->font))
+ pGC->ops->ImageGlyphBlt = s3ImageTEGlyphBlt;
+ else
+ pGC->ops->ImageGlyphBlt = s3ImageGlyphBlt;
+ }
+ }
+}