#include "mtypes.h"
#include "colormac.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_state.h"
#include "ffb_lock.h"
#include "extensions.h"
#include "enums.h"
#include "swrast/swrast.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/t_pipeline.h"
#undef STATE_TRACE
static unsigned int ffbComputeAlphaFunc(GLcontext *ctx)
{
unsigned int xclip;
GLubyte alphaRef;
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDAlphaFunc: func(%s) ref(%02x)\n",
_mesa_lookup_enum_by_nr(ctx->Color.AlphaFunc),
ctx->Color.AlphaRef & 0xff);
#endif
switch (ctx->Color.AlphaFunc) {
case GL_NEVER: xclip = FFB_XCLIP_TEST_NEVER; break;
case GL_LESS: xclip = FFB_XCLIP_TEST_LT; break;
case GL_EQUAL: xclip = FFB_XCLIP_TEST_EQ; break;
case GL_LEQUAL: xclip = FFB_XCLIP_TEST_LE; break;
case GL_GREATER: xclip = FFB_XCLIP_TEST_GT; break;
case GL_NOTEQUAL: xclip = FFB_XCLIP_TEST_NE; break;
case GL_GEQUAL: xclip = FFB_XCLIP_TEST_GE; break;
case GL_ALWAYS: xclip = FFB_XCLIP_TEST_ALWAYS; break;
default:
return FFB_XCLIP_TEST_ALWAYS | 0x00;
}
CLAMPED_FLOAT_TO_UBYTE(alphaRef, ctx->Color.AlphaRef);
xclip |= (alphaRef & 0xff);
return xclip;
}
static void ffbDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
if (ctx->Color.AlphaEnabled) {
unsigned int xclip = ffbComputeAlphaFunc(ctx);
if (fmesa->xclip != xclip) {
fmesa->xclip = xclip;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_XCLIP, 1);
}
}
}
static void ffbDDBlendEquation(GLcontext *ctx, GLenum mode)
{
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDBlendEquation: mode(%s)\n", _mesa_lookup_enum_by_nr(mode));
#endif
FALLBACK( ctx, (mode != GL_FUNC_ADD_EXT), FFB_BADATTR_BLENDEQN);
}
static void ffbDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
unsigned int blendc = 1 << 4;
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDBlendFunc: sfactor(%s) dfactor(%s)\n",
_mesa_lookup_enum_by_nr(sfactor), _mesa_lookup_enum_by_nr(dfactor));
#endif
switch (ctx->Color.BlendSrcRGB) {
case GL_ZERO:
blendc |= (0 << 0);
break;
case GL_ONE:
blendc |= (1 << 0);
break;
case GL_ONE_MINUS_SRC_ALPHA:
blendc |= (2 << 0);
break;
case GL_SRC_ALPHA:
blendc |= (3 << 0);
break;
default:
if (ctx->Color.BlendEnabled)
FALLBACK( ctx, FFB_BADATTR_BLENDFUNC, GL_TRUE );
return;
};
switch (ctx->Color.BlendDstRGB) {
case GL_ZERO:
blendc |= (0 << 2);
break;
case GL_ONE:
blendc |= (1 << 2);
break;
case GL_ONE_MINUS_SRC_ALPHA:
blendc |= (2 << 2);
break;
case GL_SRC_ALPHA:
blendc |= (3 << 2);
break;
default:
if (ctx->Color.BlendEnabled)
FALLBACK( ctx, FFB_BADATTR_BLENDFUNC, GL_TRUE );
return;
};
if (ctx->Color.BlendEnabled &&
ctx->Color.ColorLogicOpEnabled &&
ctx->Color.LogicOp != GL_COPY) {
FALLBACK(ctx, FFB_BADATTR_BLENDROP, GL_TRUE);
return;
}
FALLBACK( ctx, (FFB_BADATTR_BLENDFUNC|FFB_BADATTR_BLENDROP), GL_FALSE );
if (blendc != fmesa->blendc) {
fmesa->blendc = blendc;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_BLEND, 1);
}
}
static void ffbDDBlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB,
GLenum dfactorRGB, GLenum sfactorA,
GLenum dfactorA)
{
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDBlendFuncSeparate: sRGB(%s) dRGB(%s) sA(%s) dA(%s)\n",
_mesa_lookup_enum_by_nr(sfactorRGB),
_mesa_lookup_enum_by_nr(dfactorRGB),
_mesa_lookup_enum_by_nr(sfactorA),
_mesa_lookup_enum_by_nr(dfactorA));
#endif
ffbDDBlendFunc(ctx, sfactorRGB, dfactorRGB);
}
static void ffbDDDepthFunc(GLcontext *ctx, GLenum func)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
GLuint cmp;
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDDepthFunc: func(%s)\n",
_mesa_lookup_enum_by_nr(func));
#endif
switch (func) {
case GL_NEVER:
cmp = FFB_CMP_MAGN_NEVER;
break;
case GL_ALWAYS:
cmp = FFB_CMP_MAGN_ALWAYS;
break;
case GL_LESS:
cmp = FFB_CMP_MAGN_LT;
break;
case GL_LEQUAL:
cmp = FFB_CMP_MAGN_LE;
break;
case GL_EQUAL:
cmp = FFB_CMP_MAGN_EQ;
break;
case GL_GREATER:
cmp = FFB_CMP_MAGN_GT;
break;
case GL_GEQUAL:
cmp = FFB_CMP_MAGN_GE;
break;
case GL_NOTEQUAL:
cmp = FFB_CMP_MAGN_NE;
break;
default:
return;
};
if (! ctx->Depth.Test)
cmp = FFB_CMP_MAGN_ALWAYS;
cmp <<= 16;
cmp = (fmesa->cmp & ~(0xff<<16)) | cmp;
if (cmp != fmesa->cmp) {
fmesa->cmp = cmp;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_CMP, 1);
}
}
static void ffbDDDepthMask(GLcontext *ctx, GLboolean flag)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
GLuint fbc = fmesa->fbc;
GLboolean enabled_now;
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDDepthMask: flag(%d)\n", flag);
#endif
if ((fbc & FFB_FBC_ZE_MASK) == FFB_FBC_ZE_OFF)
enabled_now = GL_FALSE;
else
enabled_now = GL_TRUE;
if (flag != enabled_now) {
fbc &= ~FFB_FBC_ZE_MASK;
if (flag) {
fbc |= FFB_FBC_WB_C | FFB_FBC_ZE_ON;
} else {
fbc |= FFB_FBC_ZE_OFF;
fbc &= ~FFB_FBC_WB_C;
}
fmesa->fbc = fbc;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
}
}
static void ffbDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref, GLuint mask)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
unsigned int stencil, stencilctl, consty;
if (! ctx->Stencil.Enabled)
return;
stencilctl = fmesa->stencilctl;
stencilctl &= ~(7 << 16);
switch (func) {
case GL_ALWAYS: stencilctl |= (0 << 16); break;
case GL_GREATER: stencilctl |= (1 << 16); break;
case GL_EQUAL: stencilctl |= (2 << 16); break;
case GL_GEQUAL: stencilctl |= (3 << 16); break;
case GL_NEVER: stencilctl |= (4 << 16); break;
case GL_LEQUAL: stencilctl |= (5 << 16); break;
case GL_NOTEQUAL: stencilctl |= (6 << 16); break;
case GL_LESS: stencilctl |= (7 << 16); break;
default:
return;
};
consty = ref & 0xf;
stencil = fmesa->stencil;
stencil &= ~(0xf << 20);
stencil |= (mask & 0xf) << 20;
if (fmesa->stencil != stencil ||
fmesa->stencilctl != stencilctl ||
fmesa->consty != consty) {
fmesa->stencil = stencil;
fmesa->stencilctl = stencilctl;
fmesa->consty = consty;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6);
}
}
static void ffbDDStencilMask(GLcontext *ctx, GLuint mask)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
mask &= 0xf;
if (fmesa->ypmask != mask) {
fmesa->ypmask = mask;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_YPMASK, 1);
}
}
static void ffbDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
unsigned int stencilctl;
if (! ctx->Stencil.Enabled)
return;
stencilctl = fmesa->stencilctl;
stencilctl &= ~(0xfff00000);
switch (fail) {
case GL_ZERO: stencilctl |= (0 << 28); break;
case GL_KEEP: stencilctl |= (1 << 28); break;
case GL_INVERT: stencilctl |= (2 << 28); break;
case GL_REPLACE: stencilctl |= (3 << 28); break;
case GL_INCR: stencilctl |= (4 << 28); break;
case GL_DECR: stencilctl |= (5 << 28); break;
default:
return;
};
switch (zfail) {
case GL_ZERO: stencilctl |= (0 << 24); break;
case GL_KEEP: stencilctl |= (1 << 24); break;
case GL_INVERT: stencilctl |= (2 << 24); break;
case GL_REPLACE: stencilctl |= (3 << 24); break;
case GL_INCR: stencilctl |= (4 << 24); break;
case GL_DECR: stencilctl |= (5 << 24); break;
default:
return;
};
switch (zpass) {
case GL_ZERO: stencilctl |= (0 << 20); break;
case GL_KEEP: stencilctl |= (1 << 20); break;
case GL_INVERT: stencilctl |= (2 << 20); break;
case GL_REPLACE: stencilctl |= (3 << 20); break;
case GL_INCR: stencilctl |= (4 << 20); break;
case GL_DECR: stencilctl |= (5 << 20); break;
default:
return;
};
if (fmesa->stencilctl != stencilctl) {
fmesa->stencilctl = stencilctl;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6);
}
}
static void ffbCalcViewportRegs(GLcontext *ctx)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = fmesa->driDrawable;
GLuint xmin, xmax, ymin, ymax, zmin, zmax;
unsigned int vcmin, vcmax;
xmin = ctx->Viewport.X + dPriv->x;
xmax = xmin + ctx->Viewport.Width;
ymax = dPriv->y + dPriv->h - ctx->Viewport.Y;
ymin = ymax - ctx->Viewport.Height;
if (ctx->Scissor.Enabled) {
GLuint sc_xmin, sc_xmax, sc_ymin, sc_ymax;
sc_xmin = ctx->Viewport.X + dPriv->x;
sc_xmax = sc_xmin + ctx->Viewport.Width;
sc_ymax = dPriv->y + dPriv->h - ctx->Viewport.Y;
sc_ymin = sc_ymax - ctx->Viewport.Height;
if (sc_xmin > xmin)
xmin = sc_xmin;
if (sc_xmax < xmax)
xmax = sc_xmax;
if (sc_ymin > ymin)
ymin = sc_ymin;
if (sc_ymax < ymax)
ymax = sc_ymax;
}
zmin = ((GLdouble)ctx->Viewport.Near * 0x0fffffff);
zmax = ((GLdouble)ctx->Viewport.Far * 0x0fffffff);
vcmin = ((ymin & 0xffff) << 16) | (xmin & 0xffff);
vcmax = ((ymax & 0xffff) << 16) | (xmax & 0xffff);
if (fmesa->vclipmin != vcmin ||
fmesa->vclipmax != vcmax ||
fmesa->vclipzmin != zmin ||
fmesa->vclipzmax != zmax) {
fmesa->vclipmin = vcmin;
fmesa->vclipmax = vcmax;
fmesa->vclipzmin = zmin;
fmesa->vclipzmax = zmax;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_CLIP, (4 + (4 * 2)));
}
}
void ffbCalcViewport(GLcontext *ctx)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
const GLfloat *v = ctx->Viewport._WindowMap.m;
GLfloat *m = fmesa->hw_viewport;
__DRIdrawablePrivate *dPriv = fmesa->driDrawable;
m[MAT_SX] = v[MAT_SX];
m[MAT_TX] = v[MAT_TX] + dPriv->x + SUBPIXEL_X;
m[MAT_SY] = - v[MAT_SY];
m[MAT_TY] = - v[MAT_TY] + dPriv->h + dPriv->y + SUBPIXEL_Y;
m[MAT_SZ] = v[MAT_SZ] * ((GLdouble)1.0 / (GLdouble)0x0fffffff);
m[MAT_TZ] = v[MAT_TZ] * ((GLdouble)1.0 / (GLdouble)0x0fffffff);
fmesa->depth_scale = ((GLdouble)1.0 / (GLdouble)0x0fffffff);
ffbCalcViewportRegs(ctx);
fmesa->setupnewinputs |= VERT_BIT_CLIP;
}
static void ffbDDViewport(GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height)
{
ffbCalcViewport(ctx);
}
static void ffbDDDepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
{
ffbCalcViewport(ctx);
}
static void ffbDDScissor(GLcontext *ctx, GLint cx, GLint cy,
GLsizei cw, GLsizei ch)
{
ffbCalcViewport(ctx);
}
static void ffbDDDrawBuffer(GLcontext *ctx, GLenum buffer)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
unsigned int fbc = fmesa->fbc;
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDDrawBuffer: mode(%s)\n",
_mesa_lookup_enum_by_nr(buffer));
#endif
fbc &= ~(FFB_FBC_WB_AB | FFB_FBC_RB_MASK);
switch (buffer) {
case FRONT_LEFT_BIT:
if (fmesa->back_buffer == 0)
fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B;
else
fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
break;
case BACK_LEFT_BIT:
if (fmesa->back_buffer == 0)
fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
else
fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B;
break;
case BACK_LEFT_BIT | FRONT_LEFT_BIT:
fbc |= FFB_FBC_WB_AB;
break;
default:
return;
};
if (fbc != fmesa->fbc) {
fmesa->fbc = fbc;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
}
}
static void ffbDDReadBuffer(GLcontext *ctx, GLenum buffer)
{
}
static void ffbDDSetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer,
GLuint bufferBit)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
unsigned int fbc = fmesa->fbc;
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDSetReadBuffer: mode(%s)\n",
_mesa_lookup_enum_by_nr(buffer));
#endif
fbc &= ~(FFB_FBC_RB_MASK);
switch (bufferBit) {
case FRONT_LEFT_BIT:
if (fmesa->back_buffer == 0)
fbc |= FFB_FBC_RB_B;
else
fbc |= FFB_FBC_RB_A;
break;
case BACK_LEFT_BIT:
if (fmesa->back_buffer == 0)
fbc |= FFB_FBC_RB_A;
else
fbc |= FFB_FBC_RB_B;
break;
default:
return;
};
if (fbc != fmesa->fbc) {
fmesa->fbc = fbc;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
}
}
static void ffbDDClearColor(GLcontext *ctx, const GLfloat color[4])
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
GLubyte c[4];
CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
fmesa->clear_pixel = ((c[0] << 0) |
(c[1] << 8) |
(c[2] << 16));
}
static void ffbDDClearDepth(GLcontext *ctx, GLclampd depth)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
fmesa->clear_depth = Z_FROM_MESA(depth * 4294967295.0f);
}
static void ffbDDClearStencil(GLcontext *ctx, GLint stencil)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
fmesa->clear_stencil = stencil & 0xf;
}
static void ffbDDColorMask(GLcontext *ctx,
GLboolean r, GLboolean g,
GLboolean b, GLboolean a)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
unsigned int new_pmask = 0x0;
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDColorMask: r(%d) g(%d) b(%d) a(%d)\n",
r, g, b, a);
#endif
if (r)
new_pmask |= 0x000000ff;
if (g)
new_pmask |= 0x0000ff00;
if (b)
new_pmask |= 0x00ff0000;
if (fmesa->pmask != new_pmask) {
fmesa->pmask = new_pmask;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_PMASK, 1);
}
}
static void ffbDDLogicOp(GLcontext *ctx, GLenum op)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
unsigned int rop;
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDLogicOp: op(%s)\n",
_mesa_lookup_enum_by_nr(op));
#endif
switch (op) {
case GL_CLEAR: rop = FFB_ROP_ZERO; break;
case GL_SET: rop = FFB_ROP_ONES; break;
case GL_COPY: rop = FFB_ROP_NEW; break;
case GL_AND: rop = FFB_ROP_NEW_AND_OLD; break;
case GL_NAND: rop = FFB_ROP_NEW_AND_NOLD; break;
case GL_OR: rop = FFB_ROP_NEW_OR_OLD; break;
case GL_NOR: rop = FFB_ROP_NEW_OR_NOLD; break;
case GL_XOR: rop = FFB_ROP_NEW_XOR_OLD; break;
case GL_NOOP: rop = FFB_ROP_OLD; break;
case GL_COPY_INVERTED: rop = FFB_ROP_NNEW; break;
case GL_INVERT: rop = FFB_ROP_NOLD; break;
case GL_EQUIV: rop = FFB_ROP_NNEW_XOR_NOLD; break;
case GL_AND_REVERSE: rop = FFB_ROP_NEW_AND_NOLD; break;
case GL_AND_INVERTED: rop = FFB_ROP_NNEW_AND_OLD; break;
case GL_OR_REVERSE: rop = FFB_ROP_NEW_OR_NOLD; break;
case GL_OR_INVERTED: rop = FFB_ROP_NNEW_OR_OLD; break;
default:
return;
};
rop |= fmesa->rop & ~0xff;
if (rop != fmesa->rop) {
fmesa->rop = rop;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_ROP, 1);
if (op == GL_COPY)
FALLBACK( ctx, FFB_BADATTR_BLENDROP, GL_FALSE );
}
}
#if 0
static void ffb_fog_linear(GLcontext *ctx, ffbContextPtr fmesa)
{
GLfloat c = ctx->ProjectionMatrix.m[10];
GLfloat d = ctx->ProjectionMatrix.m[14];
GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
GLfloat fogEnd = ctx->Fog.End;
GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
GLfloat ndcz;
GLfloat eyez;
GLfloat Zzero, Zone;
unsigned int zb, zf;
Zzero = (((-d / fogEnd) - c) / szInv) + tz;
Zone = (((-d / (fogEnd - 1.0)) - c) / szInv) + tz;
if (Zzero < Zone) {
sf = 0.0;
sb = 1.0;
zf = Z_FROM_MESA(Zzero);
zb = Z_FROM_MESA(Zone);
} else {
sf = 1.0;
sb = 0.0;
zf = Z_FROM_MESA(Zone);
zb = Z_FROM_MESA(Zzero);
}
}
#endif
static void ffbDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
{
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDFogfv: pname(%s)\n", _mesa_lookup_enum_by_nr(pname));
#endif
}
static void ffbDDLineStipple(GLcontext *ctx, GLint factor, GLushort pattern)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDLineStipple: factor(%d) pattern(%04x)\n",
factor, pattern);
#endif
if (ctx->Line.StippleFlag) {
factor = ctx->Line.StippleFactor;
pattern = ctx->Line.StipplePattern;
if ((GLuint) factor > 15) {
fmesa->lpat = FFB_LPAT_BAD;
} else {
fmesa->lpat = ((factor << FFB_LPAT_SCALEVAL_SHIFT) |
(0 << FFB_LPAT_PATLEN_SHIFT) |
((pattern & 0xffff) << FFB_LPAT_PATTERN_SHIFT));
}
} else {
fmesa->lpat = 0;
}
}
void ffbXformAreaPattern(ffbContextPtr fmesa, const GLubyte *mask)
{
__DRIdrawablePrivate *dPriv = fmesa->driDrawable;
int i, lines, xoff;
lines = 0;
i = (dPriv->y + dPriv->h) & (32 - 1);
xoff = dPriv->x & (32 - 1);
while (lines++ < 32) {
GLuint raw =
(((GLuint)mask[0] << 24) |
((GLuint)mask[1] << 16) |
((GLuint)mask[2] << 8) |
((GLuint)mask[3] << 0));
fmesa->pattern[i] =
(raw << xoff) | (raw >> (32 - xoff));
i = (i - 1) & (32 - 1);
mask += 4;
}
FFB_MAKE_DIRTY(fmesa, FFB_STATE_APAT, 32);
}
static void ffbDDPolygonStipple(GLcontext *ctx, const GLubyte *mask)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDPolygonStipple: state(%d)\n",
ctx->Polygon.StippleFlag);
#endif
ffbXformAreaPattern(fmesa, mask);
}
static void ffbDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
unsigned int tmp;
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDEnable: %s state(%d)\n",
_mesa_lookup_enum_by_nr(cap), state);
#endif
switch (cap) {
case GL_ALPHA_TEST:
if (state)
tmp = ffbComputeAlphaFunc(ctx);
else
tmp = FFB_XCLIP_TEST_ALWAYS;
if (tmp != fmesa->xclip) {
fmesa->xclip = tmp;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_XCLIP, 1);
}
break;
case GL_BLEND:
tmp = (fmesa->ppc & ~FFB_PPC_ABE_MASK);
if (state) {
tmp |= FFB_PPC_ABE_ENABLE;
} else {
tmp |= FFB_PPC_ABE_DISABLE;
}
if (fmesa->ppc != tmp) {
fmesa->ppc = tmp;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_PPC, 1);
ffbDDBlendFunc(ctx, 0, 0);
}
break;
case GL_DEPTH_TEST:
if (state)
tmp = 0x0fffffff;
else
tmp = 0x00000000;
if (tmp != fmesa->magnc) {
unsigned int fbc = fmesa->fbc;
fbc &= ~FFB_FBC_ZE_MASK;
if (state)
fbc |= FFB_FBC_ZE_ON;
else
fbc |= FFB_FBC_ZE_OFF;
fmesa->fbc = fbc;
ffbDDDepthFunc(ctx, ctx->Depth.Func);
fmesa->magnc = tmp;
FFB_MAKE_DIRTY(fmesa, (FFB_STATE_MAGNC | FFB_STATE_FBC), 2);
}
break;
case GL_SCISSOR_TEST:
ffbDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
ctx->Scissor.Width, ctx->Scissor.Height);
break;
case GL_STENCIL_TEST:
if (!(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)) {
FALLBACK( ctx, FFB_BADATTR_STENCIL, state );
}
tmp = fmesa->fbc & ~FFB_FBC_YE_MASK;
if (state) {
ffbDDStencilFunc(ctx,
ctx->Stencil.Function[0],
ctx->Stencil.Ref[0],
ctx->Stencil.ValueMask[0]);
ffbDDStencilMask(ctx, ctx->Stencil.WriteMask[0]);
ffbDDStencilOp(ctx,
ctx->Stencil.FailFunc[0],
ctx->Stencil.ZFailFunc[0],
ctx->Stencil.ZPassFunc[0]);
tmp |= FFB_FBC_YE_MASK;
} else {
fmesa->stencil = 0xf0000000;
fmesa->stencilctl = 0x33300000;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6);
tmp |= FFB_FBC_YE_OFF;
}
if (tmp != fmesa->fbc) {
fmesa->fbc = tmp;
FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
}
break;
case GL_FOG:
FALLBACK( ctx, FFB_BADATTR_FOG, state );
break;
case GL_LINE_STIPPLE:
if (! state)
fmesa->lpat = 0;
else
ffbDDLineStipple(ctx,
ctx->Line.StippleFactor,
ctx->Line.StipplePattern);
break;
case GL_POLYGON_STIPPLE:
break;
default:
break;
};
}
void ffbSyncHardware(ffbContextPtr fmesa)
{
ffb_fbcPtr ffb = fmesa->regs;
unsigned int dirty;
int i;
FFBFifo(fmesa, fmesa->state_fifo_ents);
dirty = fmesa->state_dirty;
if (dirty & (FFB_STATE_FBC | FFB_STATE_PPC | FFB_STATE_DRAWOP |
FFB_STATE_ROP | FFB_STATE_LPAT | FFB_STATE_WID)) {
if (dirty & FFB_STATE_FBC)
ffb->fbc = fmesa->fbc;
if (dirty & FFB_STATE_PPC)
ffb->ppc = fmesa->ppc;
if (dirty & FFB_STATE_DRAWOP)
ffb->drawop = fmesa->drawop;
if (dirty & FFB_STATE_ROP)
ffb->rop = fmesa->rop;
if (dirty & FFB_STATE_LPAT)
ffb->rop = fmesa->lpat;
if (dirty & FFB_STATE_WID)
ffb->wid = fmesa->wid;
}
if (dirty & (FFB_STATE_PMASK | FFB_STATE_XPMASK | FFB_STATE_YPMASK |
FFB_STATE_ZPMASK | FFB_STATE_XCLIP | FFB_STATE_CMP |
FFB_STATE_MATCHAB | FFB_STATE_MAGNAB | FFB_STATE_MATCHC |
FFB_STATE_MAGNC)) {
if (dirty & FFB_STATE_PMASK)
ffb->pmask = fmesa->pmask;
if (dirty & FFB_STATE_XPMASK)
ffb->xpmask = fmesa->xpmask;
if (dirty & FFB_STATE_YPMASK)
ffb->ypmask = fmesa->ypmask;
if (dirty & FFB_STATE_ZPMASK)
ffb->zpmask = fmesa->zpmask;
if (dirty & FFB_STATE_XCLIP)
ffb->xclip = fmesa->xclip;
if (dirty & FFB_STATE_CMP)
ffb->cmp = fmesa->cmp;
if (dirty & FFB_STATE_MATCHAB)
ffb->matchab = fmesa->matchab;
if (dirty & FFB_STATE_MAGNAB)
ffb->magnab = fmesa->magnab;
if (dirty & FFB_STATE_MATCHC)
ffb->matchc = fmesa->matchc;
if (dirty & FFB_STATE_MAGNC)
ffb->magnc = fmesa->magnc;
}
if (dirty & FFB_STATE_DCUE) {
ffb->dcss = fmesa->dcss;
ffb->dcsf = fmesa->dcsf;
ffb->dcsb = fmesa->dcsb;
ffb->dczf = fmesa->dczf;
ffb->dczb = fmesa->dczb;
if (fmesa->ffb_sarea->flags & (FFB_DRI_FFB2 | FFB_DRI_FFB2PLUS)) {
ffb->dcss1 = fmesa->dcss1;
ffb->dcss2 = fmesa->dcss2;
ffb->dcss3 = fmesa->dcss3;
ffb->dcs2 = fmesa->dcs2;
ffb->dcs3 = fmesa->dcs3;
ffb->dcs4 = fmesa->dcs4;
ffb->dcd2 = fmesa->dcd2;
ffb->dcd3 = fmesa->dcd3;
ffb->dcd4 = fmesa->dcd4;
}
}
if (dirty & FFB_STATE_BLEND) {
ffb->blendc = fmesa->blendc;
ffb->blendc1 = fmesa->blendc1;
ffb->blendc2 = fmesa->blendc2;
}
if (dirty & FFB_STATE_CLIP) {
ffb->vclipmin = fmesa->vclipmin;
ffb->vclipmax = fmesa->vclipmax;
ffb->vclipzmin = fmesa->vclipzmin;
ffb->vclipzmax = fmesa->vclipzmax;
for (i = 0; i < 4; i++) {
ffb->auxclip[i].min = fmesa->aux_clips[i].min;
ffb->auxclip[i].max = fmesa->aux_clips[i].max;
}
}
if ((dirty & FFB_STATE_STENCIL) &&
(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)) {
ffb->stencil = fmesa->stencil;
ffb->stencilctl = fmesa->stencilctl;
ffb->fbc = FFB_FBC_WB_C;
ffb->rawstencilctl = (fmesa->stencilctl | (1 << 19));
ffb->fbc = fmesa->fbc;
ffb->consty = fmesa->consty;
}
if (dirty & FFB_STATE_APAT) {
for (i = 0; i < 32; i++)
ffb->pattern[i] = fmesa->pattern[i];
}
fmesa->state_dirty = 0;
fmesa->state_fifo_ents = 0;
fmesa->ffbScreen->rp_active = 1;
}
static void ffbDDUpdateState(GLcontext *ctx, GLuint newstate)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
if (fmesa->bad_fragment_attrs == 0 &&
(newstate & ~_NEW_COLOR) == 0)
return;
_swrast_InvalidateState( ctx, newstate );
_swsetup_InvalidateState( ctx, newstate );
_ac_InvalidateState( ctx, newstate );
_tnl_InvalidateState( ctx, newstate );
if (newstate & _NEW_TEXTURE)
FALLBACK( ctx, FFB_BADATTR_TEXTURE,
(ctx->Texture._EnabledUnits != 0));
#ifdef STATE_TRACE
fprintf(stderr, "ffbDDUpdateState: newstate(%08x)\n", newstate);
#endif
fmesa->new_gl_state |= newstate;
fmesa->raster_primitive = GL_POLYGON + 1;
#if 0
if (ctx->Fog.Enabled && (newstate & _NEW_MODELVIEW))
ffb_update_fog();
#endif
}
void ffbDDInitStateFuncs(GLcontext *ctx)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
ctx->Driver.UpdateState = ffbDDUpdateState;
ctx->Driver.Enable = ffbDDEnable;
ctx->Driver.LightModelfv = NULL;
ctx->Driver.AlphaFunc = ffbDDAlphaFunc;
ctx->Driver.BlendEquation = ffbDDBlendEquation;
ctx->Driver.BlendFunc = ffbDDBlendFunc;
ctx->Driver.BlendFuncSeparate = ffbDDBlendFuncSeparate;
ctx->Driver.DepthFunc = ffbDDDepthFunc;
ctx->Driver.DepthMask = ffbDDDepthMask;
ctx->Driver.Fogfv = ffbDDFogfv;
ctx->Driver.LineStipple = ffbDDLineStipple;
ctx->Driver.PolygonStipple = ffbDDPolygonStipple;
ctx->Driver.Scissor = ffbDDScissor;
ctx->Driver.CullFace = NULL;
ctx->Driver.FrontFace = NULL;
ctx->Driver.ColorMask = ffbDDColorMask;
ctx->Driver.LogicOpcode = ffbDDLogicOp;
ctx->Driver.Viewport = ffbDDViewport;
ctx->Driver.DepthRange = ffbDDDepthRange;
if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS) {
ctx->Driver.StencilFunc = ffbDDStencilFunc;
ctx->Driver.StencilMask = ffbDDStencilMask;
ctx->Driver.StencilOp = ffbDDStencilOp;
} else {
ctx->Driver.StencilFunc = NULL;
ctx->Driver.StencilMask = NULL;
ctx->Driver.StencilOp = NULL;
}
ctx->Driver.DrawBuffer = ffbDDDrawBuffer;
ctx->Driver.ReadBuffer = ffbDDReadBuffer;
ctx->Driver.ClearColor = ffbDDClearColor;
ctx->Driver.ClearDepth = ffbDDClearDepth;
ctx->Driver.ClearStencil = ffbDDClearStencil;
ctx->Driver.ClearIndex = 0;
ctx->Driver.IndexMask = 0;
ctx->Driver.Accum = _swrast_Accum;
ctx->Driver.CopyPixels = _swrast_CopyPixels;
ctx->Driver.DrawPixels = _swrast_DrawPixels;
ctx->Driver.ReadPixels = _swrast_ReadPixels;
ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
{
struct swrast_device_driver *swdd =
_swrast_GetDeviceDriverReference(ctx);
swdd->SetBuffer = ffbDDSetBuffer;
}
}
void ffbDDInitContextHwState(GLcontext *ctx)
{
ffbContextPtr fmesa = FFB_CONTEXT(ctx);
int fifo_count = 0;
int i;
fmesa->hw_locked = 0;
fmesa->bad_fragment_attrs = 0;
fmesa->state_dirty = FFB_STATE_ALL;
fmesa->new_gl_state = ~0;
fifo_count = 1;
fmesa->fbc = (FFB_FBC_WE_FORCEON | FFB_FBC_WM_COMBINED |
FFB_FBC_SB_BOTH | FFB_FBC_ZE_MASK |
FFB_FBC_YE_OFF | FFB_FBC_XE_OFF |
FFB_FBC_RGBE_MASK);
if (ctx->Visual.doubleBufferMode) {
fmesa->back_buffer = 1;
fmesa->fbc |= FFB_FBC_WB_BC | FFB_FBC_RB_B;
} else {
fmesa->back_buffer = 0;
fmesa->fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
}
fifo_count += 1;
fmesa->ppc = (FFB_PPC_ACE_DISABLE | FFB_PPC_DCE_DISABLE |
FFB_PPC_ABE_DISABLE | FFB_PPC_VCE_3D |
FFB_PPC_APE_DISABLE | FFB_PPC_TBE_OPAQUE |
FFB_PPC_ZS_CONST | FFB_PPC_YS_CONST |
FFB_PPC_XS_WID | FFB_PPC_CS_VAR);
fifo_count += 3;
fmesa->drawop = FFB_DRAWOP_RECTANGLE;
fmesa->rop = (FFB_ROP_NEW << 16) | (FFB_ROP_NEW << 8) | FFB_ROP_NEW;
fmesa->lpat = 0x00000000;
fifo_count += 1;
fmesa->wid = ~0;
fifo_count += 5;
fmesa->pmask = 0xffffffff;
fmesa->xpmask = 0x000000ff;
fmesa->ypmask = 0x0000000f;
fmesa->zpmask = 0x0fffffff;
fmesa->xclip = FFB_XCLIP_TEST_ALWAYS | 0x00;
fifo_count += 5;
fmesa->cmp = ((FFB_CMP_MATCH_ALWAYS << 24) |
(FFB_CMP_MAGN_ALWAYS << 16) |
(FFB_CMP_MATCH_EQ << 8) |
(FFB_CMP_MAGN_ALWAYS << 0));
fmesa->matchab = 0xff000000;
fmesa->magnab = 0x00000000;
fmesa->matchc = 0x00000000;
fmesa->magnc = 0x00000000;
fifo_count += 14;
fmesa->dcss = 0x00000000;
fmesa->dcsf = 0x00000000;
fmesa->dcsb = 0x00000000;
fmesa->dczf = 0x00000000;
fmesa->dczb = 0x00000000;
fmesa->dcss1 = 0x00000000;
fmesa->dcss2 = 0x00000000;
fmesa->dcss3 = 0x00000000;
fmesa->dcs2 = 0x00000000;
fmesa->dcs3 = 0x00000000;
fmesa->dcs4 = 0x00000000;
fmesa->dcd2 = 0x00000000;
fmesa->dcd3 = 0x00000000;
fmesa->dcd4 = 0x00000000;
fifo_count += 3;
fmesa->blendc = (1 << 0) | (0 << 2);
fmesa->blendc1 = 0x00000000;
fmesa->blendc2 = 0x00000000;
fifo_count += 4 + (4 * 2);
fmesa->vclipmin = 0x00000000;
fmesa->vclipmax = 0xffffffff;
fmesa->vclipzmin = 0x00000000;
fmesa->vclipzmax = 0x0fffffff;
for (i = 0; i < 4; i++) {
fmesa->aux_clips[0].min = 0x00000000;
fmesa->aux_clips[0].max = 0x00000000;
}
fifo_count += 6;
fmesa->stencil = 0xf0000000;
fmesa->stencilctl = 0x33300000;
fmesa->consty = 0x0;
fifo_count += 32;
for (i = 0; i < 32; i++)
fmesa->pattern[i] = 0x00000000;
fmesa->state_fifo_ents = fifo_count;
fmesa->state_all_fifo_ents = fifo_count;
}