summaryrefslogtreecommitdiff
path: root/src/ffb_frect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ffb_frect.c')
-rw-r--r--src/ffb_frect.c709
1 files changed, 709 insertions, 0 deletions
diff --git a/src/ffb_frect.c b/src/ffb_frect.c
new file mode 100644
index 0000000..340efef
--- /dev/null
+++ b/src/ffb_frect.c
@@ -0,0 +1,709 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Rectangle filling.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Michal Rehacek (majkl@iname.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK, MICHAL REHACEK, OR DAVID MILLER BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_frect.c,v 1.3 2001/04/05 17:42:33 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_stip.h"
+#include "ffb_loops.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#define PAGEFILL_DISABLED(pFfb) ((pFfb)->disable_pagefill != 0)
+#define FASTFILL_AP_DISABLED(pFfb) ((pFfb)->disable_fastfill_ap != 0)
+
+void
+CreatorFillBoxStipple (DrawablePtr pDrawable, int nBox, BoxPtr pBox, CreatorStipplePtr stipple)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ ffb_fbcPtr ffb = pFfb->regs;
+ unsigned int bits[32];
+ unsigned int newalign;
+
+ FFBLOG(("CreatorFillBoxStipple: nbox(%d)\n", nBox));
+ newalign = ((pDrawable->y & 31) << 16) | (pDrawable->x & 31);
+ if (stipple->patalign != newalign) {
+ int x, y, i;
+
+ x = (pDrawable->x - (stipple->patalign & 0xffff)) & 31;
+ y = (pDrawable->y - (stipple->patalign >> 16)) & 31;
+ if (x | y) {
+ memcpy(bits, stipple->bits, sizeof(bits));
+ for (i = 0; i < 32; i++)
+ stipple->bits[(i + y) & 31] =
+ (bits[i] >> x) | (bits[i] << (32 - x));
+ stipple->inhw = 0;
+ }
+ stipple->patalign = newalign;
+ }
+
+ FFBSetStipple(pFfb, ffb, stipple,
+ FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
+ FFB_PPC_APE_MASK|FFB_PPC_CS_MASK|FFB_PPC_XS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, ~0);
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFB_WRITE_FBC(pFfb, ffb, FFB_FBC_WIN(pWin));
+ FFB_WRITE_WID(pFfb, ffb, FFB_WID_WIN(pWin));
+
+ while(nBox--) {
+ register int x, y, w, h;
+
+ x = pBox->x1;
+ y = pBox->y1;
+ w = (pBox->x2 - x);
+ h = (pBox->y2 - y);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, h, w);
+ pBox++;
+ }
+
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+enum ffb_fillrect_method { fillrect_page,
+ fillrect_fast, fillrect_fast_opaque,
+ fillrect_normal };
+
+#define BOX_AREA(__w, __h) ((int)(__w) * (int)(__h))
+
+/* Compute the page aligned box for a page mode fast fill.
+ * In 'ework' this returns greater than zero if there are some odd
+ * edges to take care of which are outside of the page aligned area.
+ * It will place less than zero there if the box is too small,
+ * indicating that a different method must be used to fill it.
+ */
+#define CreatorPageFillParms(pFfb, ffp, x, y, w, h, px, py, pw, ph, ework) \
+do { int xdiff, ydiff; \
+ int pf_bh = ffp->pagefill_height; \
+ int pf_bw = ffp->pagefill_width; \
+ py = ((y + (pf_bh - 1)) & ~(pf_bh - 1)); \
+ ydiff = py - y; \
+ px = pFfb->Pf_AlignTab[x + (pf_bw - 1)]; \
+ xdiff = px - x; \
+ ph = ((h - ydiff) & ~(pf_bh - 1)); \
+ if(ph <= 0) \
+ ework = -1; \
+ else { \
+ pw = pFfb->Pf_AlignTab[w - xdiff]; \
+ if(pw <= 0) { \
+ ework = -1; \
+ } else { \
+ ework = (((xdiff > 0) || \
+ (ydiff > 0) || \
+ ((w - pw) > 0) || \
+ ((h - ph) > 0))) ? 1 : 0; \
+ } \
+ } \
+} while(0);
+
+/* Compute fixups of non-page aligned areas after a page fill.
+ * Return the number of fixups needed.
+ */
+static __inline__ int
+CreatorComputePageFillFixups(xRectangle *fixups,
+ int x, int y, int w, int h,
+ int paligned_x, int paligned_y,
+ int paligned_w, int paligned_h)
+{
+ int nfixups = 0;
+
+ /* FastFill Left */
+ if(paligned_x != x) {
+ fixups[nfixups].x = x;
+ fixups[nfixups].y = paligned_y;
+ fixups[nfixups].width = paligned_x - x;
+ fixups[nfixups].height = paligned_h;
+ nfixups++;
+ }
+ /* FastFill Top */
+ if(paligned_y != y) {
+ fixups[nfixups].x = x;
+ fixups[nfixups].y = y;
+ fixups[nfixups].width = w;
+ fixups[nfixups].height = paligned_y - y;
+ nfixups++;
+ }
+ /* FastFill Right */
+ if((x+w) != (paligned_x+paligned_w)) {
+ fixups[nfixups].x = (paligned_x+paligned_w);
+ fixups[nfixups].y = paligned_y;
+ fixups[nfixups].width = (x+w) - fixups[nfixups].x;
+ fixups[nfixups].height = paligned_h;
+ nfixups++;
+ }
+ /* FastFill Bottom */
+ if((y+h) != (paligned_y+paligned_h)) {
+ fixups[nfixups].x = x;
+ fixups[nfixups].y = (paligned_y+paligned_h);
+ fixups[nfixups].width = w;
+ fixups[nfixups].height = (y+h) - fixups[nfixups].y;
+ nfixups++;
+ }
+ return nfixups;
+}
+
+/* Fill a set of boxes, pagefill and fastfill not allowed. */
+static void
+CreatorBoxFillNormal(FFBPtr pFfb,
+ int nbox, BoxPtr pbox)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFBLOG(("BFNormal: "));
+ if(nbox)
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ while(nbox--) {
+ register int x, y, w, h;
+
+ x = pbox->x1;
+ y = pbox->y1;
+ w = (pbox->x2 - x);
+ h = (pbox->y2 - y);
+ pbox++;
+ FFBLOG(("[%08x:%08x:%08x:%08x] ", x, y, w, h));
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, h, w);
+ }
+ FFBLOG(("\n"));
+}
+
+/* Fill a set of boxes, only non-pagemode fastfill is allowed. */
+static void
+CreatorBoxFillFast(FFBPtr pFfb,
+ int nbox, BoxPtr pbox)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFBLOG(("BFFast: "));
+ while(nbox--) {
+ struct fastfill_parms *ffp = &FFB_FFPARMS(pFfb);
+ register int x, y, w, h;
+
+ x = pbox->x1;
+ y = pbox->y1;
+ w = (pbox->x2 - x);
+ h = (pbox->y2 - y);
+ pbox++;
+ if(BOX_AREA(w, h) < ffp->fastfill_small_area) {
+ /* Too small for fastfill to be useful. */
+ FFBLOG(("NRM(%08x:%08x:%08x:%08x) ",
+ x, y, w, h));
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, h, w);
+ } else {
+ FFBLOG(("FST(%08x:%08x:%08x:%08x:[%08x:%08x]) ",
+ x, y, w, h,
+ (w + (x & (ffp->fastfill_width - 1))),
+ (h + (y & (ffp->fastfill_height - 1)))));
+ if (pFfb->ffb_res == ffb_res_high &&
+ ((x & 7) != 0 || (w & 7) != 0)) {
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ if ((x & 7) != 0) {
+ register int nx = x;
+ register int nw;
+
+ nw = 8 - (nx & 7);
+ if (nw > w)
+ nw = w;
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, nx);
+ FFB_WRITE64_2(&ffb->bh, h, nw);
+ x += nw;
+ w -= nw;
+ }
+ if ((w & 7) != 0) {
+ register int nx, nw;
+
+ nw = (w & 7);
+ nx = x + (w - nw);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, nx);
+ FFB_WRITE64_2(&ffb->bh, h, nw);
+ w -= nw;
+ }
+ if (w <= 0)
+ goto next_rect;
+ }
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_FASTFILL);
+ FFBFifo(pFfb, 10);
+ ffb->by = FFB_FASTFILL_COLOR_BLK;
+ FFB_WRITE64(&ffb->dy, 0, 0);
+ FFB_WRITE64_2(&ffb->bh,
+ ffp->fastfill_height,
+ (ffp->fastfill_width * 4));
+ FFB_WRITE64_3(&ffb->dy, y, x);
+ ffb->bh = (h + (y & (ffp->fastfill_height - 1)));
+ FFB_WRITE64(&ffb->by, FFB_FASTFILL_BLOCK,
+ (w + (x & (ffp->fastfill_width - 1))));
+ }
+ next_rect:
+ ;
+ }
+ FFBLOG(("\n"));
+}
+
+/* Fill a set of boxes, any fastfill method is allowed. */
+static void
+CreatorBoxFillPage(FFBPtr pFfb,
+ int nbox, BoxPtr pbox)
+{
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ FFBLOG(("BFPage: "));
+ while(nbox--) {
+ struct fastfill_parms *ffp = &FFB_FFPARMS(pFfb);
+ register int x, y, w, h;
+
+ x = pbox->x1;
+ y = pbox->y1;
+ w = (pbox->x2 - x);
+ h = (pbox->y2 - y);
+ pbox++;
+ if(BOX_AREA(w, h) < ffp->fastfill_small_area) {
+ /* Too small for fastfill or page fill to be useful. */
+ FFBLOG(("NRM(%08x:%08x:%08x:%08x) ",
+ x, y, w, h));
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, x);
+ FFB_WRITE64_2(&ffb->bh, h, w);
+ } else {
+ int paligned_y, paligned_x;
+ int paligned_h, paligned_w = 0;
+ int extra_work;
+
+ if (pFfb->ffb_res == ffb_res_high &&
+ ((x & 7) != 0 || (w & 7) != 0)) {
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
+ if ((x & 7) != 0) {
+ register int nx = x;
+ register int nw;
+
+ nw = 8 - (nx & 7);
+ if (nw > w)
+ nw = w;
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, nx);
+ FFB_WRITE64_2(&ffb->bh, h, nw);
+ x += nw;
+ w -= nw;
+ }
+ if ((w & 7) != 0) {
+ register int nx, nw;
+
+ nw = (w & 7);
+ nx = x + (w - nw);
+ FFBFifo(pFfb, 4);
+ FFB_WRITE64(&ffb->by, y, nx);
+ FFB_WRITE64_2(&ffb->bh, h, nw);
+ w -= nw;
+ }
+ if (w <= 0)
+ goto next_rect;
+ }
+
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_FASTFILL);
+ if((w < (ffp->pagefill_width<<1)) ||
+ (h < (ffp->pagefill_height<<1)))
+ goto do_fastfill;
+
+ CreatorPageFillParms(pFfb, ffp,
+ x, y, w, h,
+ paligned_x, paligned_y,
+ paligned_w, paligned_h, extra_work);
+
+ /* See if the aligned area is large enough for
+ * page fill to be worthwhile.
+ */
+ if(extra_work < 0 ||
+ BOX_AREA(paligned_w, paligned_h) < ffp->pagefill_small_area) {
+ do_fastfill:
+ FFBLOG(("FST(%08x:%08x:%08x:%08x:[%08x:%08x]) ",
+ x, y, w, h,
+ (w + (x & (ffp->fastfill_width - 1))),
+ (h + (y & (ffp->fastfill_height - 1)))));
+ FFBFifo(pFfb, 10);
+ ffb->by = FFB_FASTFILL_COLOR_BLK;
+ FFB_WRITE64(&ffb->dy, 0, 0);
+ FFB_WRITE64_2(&ffb->bh,
+ ffp->fastfill_height,
+ (ffp->fastfill_width * 4));
+ FFB_WRITE64_3(&ffb->dy, y, x);
+ ffb->bh = (h + (y & (ffp->fastfill_height - 1)));
+ FFB_WRITE64(&ffb->by, FFB_FASTFILL_BLOCK,
+ (w + (x & (ffp->fastfill_width - 1))));
+ } else {
+ /* Ok, page fill is worth it, let it rip. */
+ FFBLOG(("PAG(%08x:%08x:%08x:%08x) ",
+ paligned_x, paligned_y, paligned_w, paligned_h));
+ FFBFifo(pFfb, 15);
+ ffb->by = FFB_FASTFILL_COLOR_BLK;
+ FFB_WRITE64(&ffb->dy, 0, 0);
+ FFB_WRITE64_2(&ffb->bh, ffp->fastfill_height, (ffp->fastfill_width * 4));
+ ffb->by = FFB_FASTFILL_BLOCK_X;
+ FFB_WRITE64(&ffb->dy, 0, 0);
+ FFB_WRITE64_2(&ffb->bh, ffp->pagefill_height, (ffp->pagefill_width * 4));
+ FFB_WRITE64_3(&ffb->dy, paligned_y, paligned_x);
+ ffb->bh = paligned_h;
+ FFB_WRITE64(&ffb->by, FFB_FASTFILL_PAGE, paligned_w);
+
+ if(extra_work) {
+ register int nfixups;
+
+ /* Ok, we're going to do at least one fixup. */
+ nfixups = CreatorComputePageFillFixups(pFfb->Pf_Fixups,
+ x, y, w, h,
+ paligned_x, paligned_y,
+ paligned_w, paligned_h);
+
+ /* NOTE: For the highres case we have already
+ * aligned the outermost X and W coordinates.
+ * Therefore we can be assured that the fixup
+ * X and W coordinates below will be 8 pixel
+ * aligned as well. Do the math, it works. -DaveM
+ */
+
+ FFBFifo(pFfb, 5 + (nfixups * 5));
+ ffb->by = FFB_FASTFILL_COLOR_BLK;
+ FFB_WRITE64(&ffb->dy, 0, 0);
+ FFB_WRITE64_2(&ffb->bh, ffp->fastfill_height, (ffp->fastfill_width * 4));
+
+ while(--nfixups >= 0) {
+ register int xx, yy, ww, hh;
+
+ xx = pFfb->Pf_Fixups[nfixups].x;
+ yy = pFfb->Pf_Fixups[nfixups].y;
+ FFB_WRITE64(&ffb->dy, yy, xx);
+ ww = (pFfb->Pf_Fixups[nfixups].width +
+ (xx & (ffp->fastfill_width - 1)));
+ hh = (pFfb->Pf_Fixups[nfixups].height +
+ (yy & (ffp->fastfill_height - 1)));
+ FFBLOG(("FIXUP(%08x:%08x:%08x:%08x) ",
+ xx, yy, ww, hh));
+ if(nfixups != 0) {
+ ffb->by = FFB_FASTFILL_BLOCK;
+ FFB_WRITE64_2(&ffb->bh, hh, ww);
+ } else {
+ ffb->bh = hh;
+ FFB_WRITE64(&ffb->by, FFB_FASTFILL_BLOCK, ww);
+ }
+ }
+ }
+ }
+ }
+ next_rect:
+ ;
+ }
+ FFBLOG(("\n"));
+}
+
+void
+CreatorFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, unsigned long pixel)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ WindowPtr pWin = (WindowPtr) pDrawable;
+
+ FFBLOG(("CreatorFillBoxSolid: nbox(%d)\n", nBox));
+ FFB_ATTR_FFWIN(pFfb, pWin,
+ FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
+ pixel);
+ if (PAGEFILL_DISABLED(pFfb))
+ CreatorBoxFillNormal(pFfb, nBox, pBox);
+ else
+ CreatorBoxFillPage(pFfb, nBox, pBox);
+
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, pFfb->regs);
+}
+
+static void
+FFBSetStippleFast(FFBPtr pFfb, ffb_fbcPtr ffb,
+ CreatorStipplePtr stipple,
+ unsigned int ppc, unsigned int ppc_mask)
+{
+ ppc |= FFB_PPC_APE_ENABLE | FFB_PPC_TBE_TRANSPARENT | FFB_PPC_XS_WID;
+ ppc_mask |= FFB_PPC_APE_MASK | FFB_PPC_TBE_MASK | FFB_PPC_XS_MASK;
+ FFB_WRITE_PPC(pFfb, ffb, ppc, ppc_mask);
+ FFB_WRITE_ROP(pFfb, ffb, (FFB_ROP_EDIT_BIT|stipple->alu)|(FFB_ROP_NEW<<8));
+ FFB_WRITE_FG(pFfb, ffb, stipple->fg);
+ FFBFifo(pFfb, 32);
+ FFB_STIPPLE_LOAD(&ffb->pattern[0], &stipple->bits[0]);
+}
+
+static void
+FFBSetStippleFastIdentity(FFBPtr pFfb,
+ ffb_fbcPtr ffb,
+ CreatorStipplePtr stipple)
+{
+ int i;
+
+ FFB_WRITE_FG(pFfb, ffb, stipple->bg);
+ FFBFifo(pFfb, 32);
+ for(i = 0; i < 32; i++)
+ ffb->pattern[i] = ~stipple->bits[i];
+ stipple->inhw = 0;
+ pFfb->laststipple = NULL;
+}
+
+void
+CreatorPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+ xRectangle *prect;
+ RegionPtr prgnClip;
+ register BoxPtr pbox;
+ register BoxPtr pboxClipped;
+ BoxPtr pboxClippedBase;
+ BoxPtr pextent;
+ CreatorPrivGCPtr gcPriv;
+ int numRects;
+ int n;
+ int xorg, yorg;
+
+ /* No garbage please. */
+ if (nrectFill <= 0)
+ return;
+
+ gcPriv = CreatorGetGCPrivate (pGC);
+ FFBLOG(("CreatorPolyFillRect: nrect(%d) ALU(%x) STIP(%p) pmsk(%08x)\n",
+ nrectFill, pGC->alu, gcPriv->stipple, pGC->planemask));
+ prgnClip = cfbGetCompositeClip(pGC);
+ prect = prectInit;
+ 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 > 64) {
+ pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
+ if (!pboxClippedBase)
+ return;
+ } else
+ pboxClippedBase = pFfb->ClippedBoxBuf;
+
+ 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++;
+ }
+ }
+ }
+ /* Now fill the pre-clipped boxes. */
+ if(pboxClipped != pboxClippedBase) {
+ enum ffb_fillrect_method how = fillrect_page;
+ int num = (pboxClipped - pboxClippedBase);
+ int f_w = pboxClippedBase->x2 - pboxClippedBase->x1;
+ int f_h = pboxClippedBase->y2 - pboxClippedBase->y1;
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ unsigned int fbc = FFB_FBC_WIN(pWin);
+ unsigned int drawop = FFB_DRAWOP_FASTFILL;
+
+ if (PAGEFILL_DISABLED(pFfb) ||
+ pGC->alu != GXcopy ||
+ BOX_AREA(f_w, f_h) < 128) {
+ drawop = FFB_DRAWOP_RECTANGLE;
+ how = fillrect_normal;
+ } else if (gcPriv->stipple != NULL) {
+ if (FASTFILL_AP_DISABLED(pFfb)) {
+ drawop = FFB_DRAWOP_RECTANGLE;
+ how = fillrect_normal;
+ } else {
+ if ((gcPriv->stipple->alu & FFB_ROP_EDIT_BIT) != 0)
+ how = fillrect_fast;
+ else
+ how = fillrect_fast_opaque;
+ }
+ } else {
+ int all_planes;
+
+ /* Plane masks are not controllable with page fills. */
+ if (pGC->depth == 8)
+ all_planes = 0xff;
+ else
+ all_planes = 0xffffff;
+ if ((pGC->planemask & all_planes) != all_planes)
+ how = fillrect_fast;
+ }
+
+ if (how == fillrect_page) {
+ fbc &= ~(FFB_FBC_XE_MASK | FFB_FBC_RGBE_MASK);
+ fbc |= FFB_FBC_XE_ON | FFB_FBC_RGBE_ON;
+ }
+
+ /* In the high-resolution modes, the Creator3D transforms
+ * the framebuffer such that the dual-buffers present become
+ * one large single buffer. As such you need to enable both
+ * A and B write buffers for page/fast fills to work properly
+ * under this configuration. -DaveM
+ */
+ if (pFfb->ffb_res == ffb_res_high)
+ fbc |= FFB_FBC_WB_B;
+
+ /* Setup the attributes. */
+ if (gcPriv->stipple == NULL) {
+ FFB_ATTR_RAW(pFfb,
+ FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
+ FFB_PPC_APE_MASK|FFB_PPC_CS_MASK|FFB_PPC_XS_MASK,
+ pGC->planemask,
+ ((FFB_ROP_EDIT_BIT|pGC->alu)|(FFB_ROP_NEW<<8)),
+ drawop,
+ pGC->fgPixel,
+ fbc, FFB_WID_WIN(pWin));
+ } else {
+ if (how == fillrect_fast_opaque) {
+ FFBSetStippleFast(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
+ FFB_PPC_CS_MASK|FFB_PPC_XS_MASK);
+ } else {
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ FFB_PPC_CS_CONST|FFB_PPC_XS_WID,
+ FFB_PPC_CS_MASK|FFB_PPC_XS_MASK);
+ }
+ FFB_WRITE_DRAWOP(pFfb, ffb, drawop);
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ FFB_WRITE_WID(pFfb, ffb, FFB_WID_WIN(pWin));
+ }
+
+ /* Now render. */
+ if(how == fillrect_normal)
+ CreatorBoxFillNormal(pFfb, num, pboxClippedBase);
+ else if(how == fillrect_fast || how == fillrect_fast_opaque)
+ CreatorBoxFillFast(pFfb, num, pboxClippedBase);
+ else
+ CreatorBoxFillPage(pFfb, num, pboxClippedBase);
+
+ if(how == fillrect_fast_opaque) {
+ FFBSetStippleFastIdentity(pFfb, ffb, gcPriv->stipple);
+ CreatorBoxFillFast(pFfb, num, pboxClippedBase);
+ }
+
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+ }
+ if (pboxClippedBase != pFfb->ClippedBoxBuf)
+ DEALLOCATE_LOCAL (pboxClippedBase);
+}