#include "mtypes.h"
#include "extensions.h"
#include "mm.h"
#include "ffb_dd.h"
#include "ffb_span.h"
#include "ffb_depth.h"
#include "ffb_context.h"
#include "ffb_vb.h"
#include "ffb_tris.h"
#include "ffb_clear.h"
#include "ffb_lock.h"
#undef CLEAR_TRACE
#define BOX_AREA(__w, __h) ((int)(__w) * (int)(__h))
#define CreatorPageFillParms(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 = ffp->Pf_AlignTab[x + (pf_bw - 1)]; \
xdiff = px - x; \
ph = ((h - ydiff) & ~(pf_bh - 1)); \
if(ph <= 0) \
ework = -1; \
else { \
pw = ffp->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);
struct ff_fixups {
int x, y, width, height;
};
static __inline__ int
CreatorComputePageFillFixups(struct ff_fixups *fixups,
int x, int y, int w, int h,
int paligned_x, int paligned_y,
int paligned_w, int paligned_h)
{
int nfixups = 0;
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++;
}
if(paligned_y != y) {
fixups[nfixups].x = x;
fixups[nfixups].y = y;
fixups[nfixups].width = w;
fixups[nfixups].height = paligned_y - y;
nfixups++;
}
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++;
}
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;
}
static void
ffb_do_clear(ffbContextPtr fmesa, __DRIdrawablePrivate *dPriv,
GLboolean all, GLint cx, GLint cy, GLint cwidth,
GLint cheight)
{
FFBDRIPtr gDRIPriv = (FFBDRIPtr) fmesa->driScreen->pDevPriv;
ffb_fbcPtr ffb = fmesa->regs;
XF86DRIClipRectPtr box = dPriv->pClipRects;
int nc = dPriv->numClipRects;
cy = dPriv->h - cy - cheight;
cx += dPriv->x;
cy += dPriv->y;
while (nc--) {
GLint x = box[nc].x1;
GLint y = box[nc].y1;
GLint width = box[nc].x2 - x;
GLint height = box[nc].y2 - y;
int paligned_y, paligned_x;
int paligned_h, paligned_w = 0;
int extra_work;
if (!all) {
if (x < cx) {
width -= cx - x;
x = cx;
}
if (y < cy) {
height -= cy - y;
y = cy;
}
if (x + width > cx + cwidth)
width = cx + cwidth - x;
if (y + height > cy + cheight)
height = cy + cheight - y;
if (width <= 0)
continue;
if (height <= 0)
continue;
}
if (BOX_AREA(width, height) < gDRIPriv->fastfill_small_area) {
FFBFifo(fmesa, 5);
ffb->drawop = FFB_DRAWOP_RECTANGLE;
ffb->by = y;
ffb->bx = x;
ffb->bh = height;
ffb->bw = width;
continue;
}
FFBFifo(fmesa, 1);
ffb->drawop = FFB_DRAWOP_FASTFILL;
if (gDRIPriv->disable_pagefill ||
(width < (gDRIPriv->pagefill_width<<1)) ||
(height < (gDRIPriv->pagefill_height<<1)))
goto do_fastfill;
CreatorPageFillParms(gDRIPriv,
x, y, width, height,
paligned_x, paligned_y,
paligned_w, paligned_h, extra_work);
if (extra_work < 0 ||
BOX_AREA(paligned_w, paligned_h) < gDRIPriv->pagefill_small_area) {
do_fastfill:
FFBFifo(fmesa, 10);
ffb->by = FFB_FASTFILL_COLOR_BLK;
ffb->dy = 0;
ffb->dx = 0;
ffb->bh = gDRIPriv->fastfill_height;
ffb->bw = (gDRIPriv->fastfill_width * 4);
ffb->by = FFB_FASTFILL_BLOCK;
ffb->dy = y;
ffb->dx = x;
ffb->bh = (height + (y & (gDRIPriv->fastfill_height - 1)));
ffb->bx = (width + (x & (gDRIPriv->fastfill_width - 1)));
continue;
}
FFBFifo(fmesa, 15);
ffb->by = FFB_FASTFILL_COLOR_BLK;
ffb->dy = 0;
ffb->dx = 0;
ffb->bh = gDRIPriv->fastfill_height;
ffb->bw = gDRIPriv->fastfill_width * 4;
ffb->by = FFB_FASTFILL_BLOCK_X;
ffb->dy = 0;
ffb->dx = 0;
ffb->bh = gDRIPriv->pagefill_height;
ffb->bw = gDRIPriv->pagefill_width * 4;
ffb->by = FFB_FASTFILL_PAGE;
ffb->dy = paligned_y;
ffb->dx = paligned_x;
ffb->bh = paligned_h;
ffb->bx = paligned_w;
if (extra_work) {
struct ff_fixups local_fixups[4];
int nfixups;
nfixups = CreatorComputePageFillFixups(local_fixups,
x, y, width, height,
paligned_x, paligned_y,
paligned_w, paligned_h);
FFBFifo(fmesa, 5 + (nfixups * 5));
ffb->by = FFB_FASTFILL_COLOR_BLK;
ffb->dy = 0;
ffb->dx = 0;
ffb->bh = gDRIPriv->fastfill_height;
ffb->bw = gDRIPriv->fastfill_width * 4;
while (--nfixups >= 0) {
int xx, yy, ww, hh;
xx = local_fixups[nfixups].x;
yy = local_fixups[nfixups].y;
ffb->dy = yy;
ffb->dx = xx;
ww = (local_fixups[nfixups].width +
(xx & (gDRIPriv->fastfill_width - 1)));
hh = (local_fixups[nfixups].height +
(yy & (gDRIPriv->fastfill_height - 1)));
if (nfixups != 0) {
ffb->by = FFB_FASTFILL_BLOCK;
ffb->bh = hh;
ffb->bw = ww;
} else {
ffb->bh = hh;
ffb->by = FFB_FASTFILL_BLOCK;
ffb->bx = ww;
}
}
}
}
}
void ffbDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx, GLint cy, GLint cwidth, GLint cheight)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = fmesa->driDrawable;
unsigned int stcmask = DD_STENCIL_BIT;
#ifdef CLEAR_TRACE
fprintf(stderr, "ffbDDClear: mask(%08x) all(%d) "
"[x(%x)y(%x)w(%x)h(%x)]\n",
mask, (int) all, cx, cy, cwidth, cheight);
#endif
if (!(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS))
stcmask = 0;
if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | DD_DEPTH_BIT | stcmask)) {
ffb_fbcPtr ffb = fmesa->regs;
unsigned int fbc, ppc;
fbc = (FFB_FBC_XE_ON);
ppc = (FFB_PPC_ACE_DISABLE | FFB_PPC_DCE_DISABLE |
FFB_PPC_ABE_DISABLE | FFB_PPC_VCE_DISABLE |
FFB_PPC_APE_DISABLE | FFB_PPC_XS_WID |
FFB_PPC_ZS_CONST | FFB_PPC_CS_CONST);
if (mask & (DD_DEPTH_BIT | stcmask)) {
fbc |= (FFB_FBC_ZE_ON | FFB_FBC_YE_ON | FFB_FBC_WB_C);
} else
fbc |= FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF;
if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
if (mask & DD_FRONT_LEFT_BIT) {
if (fmesa->back_buffer == 0)
fbc |= FFB_FBC_WB_B;
else
fbc |= FFB_FBC_WB_A;
}
if (mask & DD_BACK_LEFT_BIT) {
if (fmesa->back_buffer == 0)
fbc |= FFB_FBC_WB_A;
else
fbc |= FFB_FBC_WB_B;
}
fbc |= FFB_FBC_RGBE_ON;
} else
fbc |= FFB_FBC_RGBE_OFF;
LOCK_HARDWARE(fmesa);
if (dPriv->numClipRects) {
FFBFifo(fmesa, 8);
ffb->fbc = fbc;
ffb->ppc = ppc;
ffb->xclip = FFB_XCLIP_TEST_ALWAYS;
ffb->cmp = 0x80808080;
ffb->rop = FFB_ROP_NEW;
if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT))
ffb->fg = fmesa->clear_pixel;
if (mask & DD_DEPTH_BIT)
ffb->constz = fmesa->clear_depth;
if (mask & stcmask)
ffb->consty = fmesa->clear_stencil;
ffb_do_clear(fmesa, dPriv, all, cx, cy, cwidth, cheight);
FFBFifo(fmesa, 6);
ffb->ppc = fmesa->ppc;
ffb->fbc = fmesa->fbc;
ffb->xclip = fmesa->xclip;
ffb->cmp = fmesa->cmp;
ffb->rop = fmesa->rop;
ffb->drawop = fmesa->drawop;
if (mask & stcmask)
ffb->consty = fmesa->consty;
fmesa->ffbScreen->rp_active = 1;
}
UNLOCK_HARDWARE(fmesa);
mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT |
DD_DEPTH_BIT | stcmask);
}
if (mask)
_swrast_Clear(ctx, mask, all, cx, cy, cwidth, cheight);
}