From f4092abdf94af6a99aff944d6264bc1284e8bdd4 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 10 Oct 2011 17:43:39 +0200 Subject: Imported nx-X11-3.1.0-1.tar.gz Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository --- .../Mesa/src/mesa/drivers/dri/ffb/ffb_state.c | 1223 ++++++++++++++++++++ 1 file changed, 1223 insertions(+) create mode 100644 nx-X11/extras/Mesa/src/mesa/drivers/dri/ffb/ffb_state.c (limited to 'nx-X11/extras/Mesa/src/mesa/drivers/dri/ffb/ffb_state.c') diff --git a/nx-X11/extras/Mesa/src/mesa/drivers/dri/ffb/ffb_state.c b/nx-X11/extras/Mesa/src/mesa/drivers/dri/ffb/ffb_state.c new file mode 100644 index 000000000..86df5b4bc --- /dev/null +++ b/nx-X11/extras/Mesa/src/mesa/drivers/dri/ffb/ffb_state.c @@ -0,0 +1,1223 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_state.c,v 1.5 2002/10/30 12:51:27 alanh Exp $ + * + * GLX Hardware Device Driver for Sun Creator/Creator3D + * Copyright (C) 2000, 2001 David S. Miller + * + * 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 + * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. + * + * + * David S. Miller + */ + +#include "mtypes.h" +#include "buffers.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 ffbDDBlendEquationSeparate(GLcontext *ctx, + GLenum modeRGB, GLenum modeA) +{ + +#ifdef STATE_TRACE + fprintf(stderr, "ffbDDBlendEquation: mode(%s)\n", + _mesa_lookup_enum_by_nr(modeRGB)); +#endif + assert( modeRGB == modeA ); + FALLBACK( ctx, (modeRGB != GL_FUNC_ADD), FFB_BADATTR_BLENDEQN); +} + +static void ffbDDBlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, + GLenum dfactorRGB, GLenum sfactorA, + GLenum dfactorA) +{ + ffbContextPtr fmesa = FFB_CONTEXT(ctx); + unsigned int blendc = 1 << 4; + +#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 + 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) { + /* We could avoid this if sfactor is GL_ONE and + * dfactor is GL_ZERO. I do not think that is even + * worthwhile to check because if someone is using + * blending they use more interesting settings and + * also it would add more state tracking to a lot + * of the code in this file. + */ + 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 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; + + /* We will properly update sw/hw state when stenciling is + * enabled. + */ + 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; + + /* We will properly update sw/hw state when stenciling is + * enabled. + */ + 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_POS; +} + +static void ffbDDViewport(GLcontext *ctx, GLint x, GLint y, + GLsizei width, GLsizei height) +{ + /* update size of Mesa/software ancillary buffers */ + _mesa_ResizeBuffersMESA(); + 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 GL_FRONT: + 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 GL_BACK: + 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 GL_FRONT_AND_BACK: + 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) +{ + /* no-op, unless you implement h/w glRead/CopyPixels */ +} + + +/* + * Specifies buffer for sw fallbacks (spans) + */ +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 BUFFER_BIT_FRONT_LEFT: + if (fmesa->back_buffer == 0) + fbc |= FFB_FBC_RB_B; + else + fbc |= FFB_FBC_RB_A; + break; + + case BUFFER_BIT_BACK_LEFT: + if (fmesa->back_buffer == 0) + fbc |= FFB_FBC_RB_A; + else + fbc |= FFB_FBC_RB_B; + break; + + default: + _mesa_problem(ctx, "Unexpected buffer in ffbDDSetBuffer()"); + 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; +} + +/* XXX Actually, should I be using FBC controls for this? -DaveM */ +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 (a) + new_pmask |= 0xff000000; + + 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 +/* XXX Also need to track near/far just like 3dfx driver. + * XXX + * XXX Actually, that won't work, because the 3dfx chip works by + * XXX having 1/w coordinates fed to it for each primitive, and + * XXX it uses this to index it's 64 entry fog table. + */ +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; + + /* Compute the Z at which f reaches 0.0, this is the full + * saturation point. + * + * Thus compute Z (as seen by the chip during rendering), + * such that: + * + * 0.0 = (fogEnd - eyez) * fogScale + * + * fogScale is usually not zero, thus we are looking for: + * + * fogEnd = eyez + * + * fogEnd = -d / (c + ((Z - tz) * szInv)) + * fogEnd * (c + ((Z - tz) * szInv)) = -d + * (c + ((Z - tz) * szInv)) = -d / fogEnd + * (Z - tz) * szInv = (-d / fogEnd) - c + * (Z - tz) = ((-d / fogEnd) - c) / szInv + * Z = (((-d / fogEnd) - c) / szInv) + tz + */ + Zzero = (((-d / fogEnd) - c) / szInv) + tz; + + /* Compute the Z at which f reaches 1.0, this is where + * the incoming frag's full intensity is shown. This + * equation is: + * + * 1.0 = (fogEnd - eyez) + * + * We are looking for: + * + * 1.0 + eyez = fogEnd + * + * 1.0 + (-d / (c + ((Z - tz) * szInv))) = fogEnd + * -d / (c + ((Z - tz) * szInv)) = fogEnd - 1.0 + * -d / (FogEnd - 1.0) = (c + ((Z - tz) * szInv)) + * (-d / (fogEnd - 1.0)) - c = ((Z - tz) * szInv) + * ((-d / (fogEnd - 1.0)) - c) / szInv = (Z - tz) + * (((-d / (fogEnd - 1.0)) - c) / szInv) + tz = Z + */ + Zone = (((-d / (fogEnd - 1.0)) - c) / szInv) + tz; + + /* FFB's Zfront must be less than Zback, thus we may have + * to invert Sf/Sb to satisfy this constraint. + */ + 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); + ffbDDBlendFuncSeparate(ctx, 0, 0, 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: + /* Until I implement the fog support... */ + 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: + /* Do nothing, we interrogate the state during + * reduced primitive changes. Since our caller + * will set NEW_POLYGON in the ctx NewState this + * will cause the driver rasterization functions + * to be reevaluated, which will cause us to force + * a reduced primitive change next rendering pass + * and it all works out. + */ + 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); + + /* When we are hw rendering, changing certain kinds of + * state does not require flushing all of our context. + */ + 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; + + /* Force a reduced primitive change next rendering + * pass. + */ + fmesa->raster_primitive = GL_POLYGON + 1; + +#if 0 + /* When the modelview matrix changes, this changes what + * the eye coordinates will be so we have to recompute + * the depth cueing parameters. + * + * XXX DD_HAVE_HARDWARE_FOG. + */ + 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.AlphaFunc = ffbDDAlphaFunc; + ctx->Driver.BlendEquationSeparate = ffbDDBlendEquationSeparate; + 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.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; + } + + ctx->Driver.DrawBuffer = ffbDDDrawBuffer; + ctx->Driver.ReadBuffer = ffbDDReadBuffer; + ctx->Driver.ClearColor = ffbDDClearColor; + ctx->Driver.ClearDepth = ffbDDClearDepth; + ctx->Driver.ClearStencil = ffbDDClearStencil; + + /* We will support color index modes later... -DaveM */ + /* + ctx->Driver.ClearIndex = 0; + ctx->Driver.IndexMask = 0; + */ + + { + 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) { + /* Buffer B is the initial back buffer. */ + 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; + + /* GL_COPY is the default LogicOp. */ + fmesa->rop = (FFB_ROP_NEW << 16) | (FFB_ROP_NEW << 8) | FFB_ROP_NEW; + + /* No line patterning enabled. */ + fmesa->lpat = 0x00000000; + + /* We do not know the WID value until the first context switch. */ + fifo_count += 1; + fmesa->wid = ~0; + + fifo_count += 5; + + /* ColorMask, all enabled. */ + fmesa->pmask = 0xffffffff; + + fmesa->xpmask = 0x000000ff; + fmesa->ypmask = 0x0000000f; + fmesa->zpmask = 0x0fffffff; + + /* AlphaFunc GL_ALWAYS, AlphaRef 0 */ + fmesa->xclip = FFB_XCLIP_TEST_ALWAYS | 0x00; + + /* This sets us up to use WID clipping (so the DRI clipping + * rectangle is unneeded by us). All other match and magnitude + * tests are set to pass. + */ + fifo_count += 5; + fmesa->cmp = ((FFB_CMP_MATCH_ALWAYS << 24) | /* MATCH C */ + (FFB_CMP_MAGN_ALWAYS << 16) | /* MAGN C */ + (FFB_CMP_MATCH_EQ << 8) | /* MATCH AB */ + (FFB_CMP_MAGN_ALWAYS << 0)); /* MAGN AB */ + fmesa->matchab = 0xff000000; + fmesa->magnab = 0x00000000; + fmesa->matchc = 0x00000000; + fmesa->magnc = 0x00000000; + + /* Depth cue parameters, all zeros to start. */ + 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; + + /* Alpha blending unit state. */ + fifo_count += 3; + fmesa->blendc = (1 << 0) | (0 << 2); /* src(GL_ONE) | dst(GL_ZERO) */ + fmesa->blendc1 = 0x00000000; + fmesa->blendc2 = 0x00000000; + + /* ViewPort clip state. */ + 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; + } + + /* Stenciling state. */ + fifo_count += 6; + fmesa->stencil = 0xf0000000; /* Stencil MASK, Y plane */ + fmesa->stencilctl = 0x33300000; /* All stencil tests disabled */ + fmesa->consty = 0x0; + + /* Area pattern, used for polygon stipples. */ + 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; +} -- cgit v1.2.3