From e05ab2795b7463a053562b233d75e62f4138e0d3 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 4 Dec 2003 13:27:05 +0000 Subject: add tdfx DRI driver --- src/mesa/drivers/dri/tdfx/tdfx_state.c | 1466 ++++++++++++++++++++++++++++++++ 1 file changed, 1466 insertions(+) create mode 100644 src/mesa/drivers/dri/tdfx/tdfx_state.c (limited to 'src/mesa/drivers/dri/tdfx/tdfx_state.c') diff --git a/src/mesa/drivers/dri/tdfx/tdfx_state.c b/src/mesa/drivers/dri/tdfx/tdfx_state.c new file mode 100644 index 0000000000..bab3854a7c --- /dev/null +++ b/src/mesa/drivers/dri/tdfx/tdfx_state.c @@ -0,0 +1,1466 @@ +/* -*- mode: c; c-basic-offset: 3 -*- + * + * Copyright 2000 VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * 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 (including the next + * paragraph) 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 + * VA LINUX SYSTEMS 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/lib/GL/mesa/src/drv/tdfx/tdfx_state.c,v 1.7 2002/10/30 12:52:00 alanh Exp $ */ + +/* + * Original rewrite: + * Gareth Hughes , 29 Sep - 1 Oct 2000 + * + * Authors: + * Gareth Hughes + * Brian Paul + * Keith Whitwell (port to 3.5) + * + */ + +#include "mtypes.h" +#include "colormac.h" +#include "texformat.h" +#include "texstore.h" + +#include "swrast/swrast.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" +#include "swrast_setup/swrast_setup.h" + +#include "tdfx_context.h" +#include "tdfx_state.h" +#include "tdfx_vb.h" +#include "tdfx_tex.h" +#include "tdfx_texman.h" +#include "tdfx_texstate.h" +#include "tdfx_tris.h" +#include "tdfx_render.h" + + + +/* ============================================================= + * Alpha blending + */ + +static void tdfxUpdateAlphaMode( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + GrCmpFnc_t func; + GrAlphaBlendFnc_t srcRGB, dstRGB, srcA, dstA; + GrAlpha_t ref = (GLint) (ctx->Color.AlphaRef * 255.0); + + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s()\n", __FUNCTION__ ); + } + + if ( ctx->Color.AlphaEnabled ) { + switch ( ctx->Color.AlphaFunc ) { + case GL_NEVER: + func = GR_CMP_NEVER; + break; + case GL_LESS: + func = GR_CMP_LESS; + break; + case GL_LEQUAL: + func = GR_CMP_LEQUAL; + break; + case GL_EQUAL: + func = GR_CMP_EQUAL; + break; + case GL_GEQUAL: + func = GR_CMP_GEQUAL; + break; + case GL_GREATER: + func = GR_CMP_GREATER; + break; + case GL_NOTEQUAL: + func = GR_CMP_NOTEQUAL; + break; + case GL_ALWAYS: + default: + func = GR_CMP_ALWAYS; + break; + } + } else { + func = GR_CMP_ALWAYS; + } + + if ( ctx->Color.BlendEnabled + && (fxMesa->Fallback & TDFX_FALLBACK_BLEND) == 0 ) { + switch ( ctx->Color.BlendSrcRGB ) { + case GL_ZERO: + srcRGB = GR_BLEND_ZERO; + break; + case GL_ONE: + srcRGB = GR_BLEND_ONE; + break; + case GL_DST_COLOR: + srcRGB = GR_BLEND_DST_COLOR; + break; + case GL_ONE_MINUS_DST_COLOR: + srcRGB = GR_BLEND_ONE_MINUS_DST_COLOR; + break; + case GL_SRC_ALPHA: + srcRGB = GR_BLEND_SRC_ALPHA; + break; + case GL_ONE_MINUS_SRC_ALPHA: + srcRGB = GR_BLEND_ONE_MINUS_SRC_ALPHA; + break; + case GL_DST_ALPHA: + srcRGB = GR_BLEND_DST_ALPHA; + break; + case GL_ONE_MINUS_DST_ALPHA: + srcRGB = GR_BLEND_ONE_MINUS_DST_ALPHA; + break; + case GL_SRC_ALPHA_SATURATE: + srcRGB = GR_BLEND_ALPHA_SATURATE; + break; + default: + srcRGB = GR_BLEND_ONE; + } + + switch ( ctx->Color.BlendSrcA ) { + case GL_ZERO: + srcA = GR_BLEND_ZERO; + break; + case GL_ONE: + srcA = GR_BLEND_ONE; + break; + case GL_DST_COLOR: + srcA = GR_BLEND_DST_ALPHA; /* Napalm only */ + break; + case GL_ONE_MINUS_DST_COLOR: + srcA = GR_BLEND_ONE_MINUS_DST_ALPHA; /* Napalm only */ + break; + case GL_SRC_ALPHA: + srcA = GR_BLEND_SRC_ALPHA; /* Napalm only */ + break; + case GL_ONE_MINUS_SRC_ALPHA: + srcA = GR_BLEND_ONE_MINUS_SRC_ALPHA; /* Napalm only */ + break; + case GL_DST_ALPHA: + srcA = GR_BLEND_DST_ALPHA; /* Napalm only */ + break; + case GL_ONE_MINUS_DST_ALPHA: + srcA = GR_BLEND_ONE_MINUS_DST_ALPHA; /* Napalm only */ + break; + case GL_SRC_ALPHA_SATURATE: + srcA = GR_BLEND_ONE; + break; + default: + srcA = GR_BLEND_ONE; + } + + switch ( ctx->Color.BlendDstRGB ) { + case GL_ZERO: + dstRGB = GR_BLEND_ZERO; + break; + case GL_ONE: + dstRGB = GR_BLEND_ONE; + break; + case GL_SRC_COLOR: + dstRGB = GR_BLEND_SRC_COLOR; + break; + case GL_ONE_MINUS_SRC_COLOR: + dstRGB = GR_BLEND_ONE_MINUS_SRC_COLOR; + break; + case GL_SRC_ALPHA: + dstRGB = GR_BLEND_SRC_ALPHA; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dstRGB = GR_BLEND_ONE_MINUS_SRC_ALPHA; + break; + case GL_DST_ALPHA: + dstRGB = GR_BLEND_DST_ALPHA; + break; + case GL_ONE_MINUS_DST_ALPHA: + dstRGB = GR_BLEND_ONE_MINUS_DST_ALPHA; + break; + default: + dstRGB = GR_BLEND_ZERO; + } + + switch ( ctx->Color.BlendDstA ) { + case GL_ZERO: + dstA = GR_BLEND_ZERO; + break; + case GL_ONE: + dstA = GR_BLEND_ONE; + break; + case GL_SRC_COLOR: + dstA = GR_BLEND_SRC_ALPHA; /* Napalm only */ + break; + case GL_ONE_MINUS_SRC_COLOR: + dstA = GR_BLEND_ONE_MINUS_SRC_ALPHA; /* Napalm only */ + break; + case GL_SRC_ALPHA: + dstA = GR_BLEND_SRC_ALPHA; /* Napalm only */ + break; + case GL_ONE_MINUS_SRC_ALPHA: + dstA = GR_BLEND_ONE_MINUS_SRC_ALPHA; /* Napalm only */ + break; + case GL_DST_ALPHA: + dstA = GR_BLEND_DST_ALPHA; /* Napalm only */ + break; + case GL_ONE_MINUS_DST_ALPHA: + dstA = GR_BLEND_ONE_MINUS_DST_ALPHA; /* Napalm only */ + break; + default: + dstA = GR_BLEND_ZERO; + } + } else { + /* blend disabled */ + srcRGB = GR_BLEND_ONE; + dstRGB = GR_BLEND_ZERO; + srcA = GR_BLEND_ONE; + dstA = GR_BLEND_ZERO; + } + + if ( fxMesa->Color.AlphaFunc != func ) { + fxMesa->Color.AlphaFunc = func; + fxMesa->dirty |= TDFX_UPLOAD_ALPHA_TEST; + } + if ( fxMesa->Color.AlphaRef != ref ) { + fxMesa->Color.AlphaRef = ref; + fxMesa->dirty |= TDFX_UPLOAD_ALPHA_REF; + } + + if ( fxMesa->Color.BlendSrcRGB != srcRGB || + fxMesa->Color.BlendDstRGB != dstRGB || + fxMesa->Color.BlendSrcA != srcA || + fxMesa->Color.BlendDstA != dstA ) + { + fxMesa->Color.BlendSrcRGB = srcRGB; + fxMesa->Color.BlendDstRGB = dstRGB; + fxMesa->Color.BlendSrcA = srcA; + fxMesa->Color.BlendDstA = dstA; + fxMesa->dirty |= TDFX_UPLOAD_BLEND_FUNC; + } +} + +static void tdfxDDAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_ALPHA; +} + +static void tdfxDDBlendEquation( GLcontext *ctx, GLenum mode ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_ALPHA; +} + +static void tdfxDDBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_ALPHA; + + /* + * XXX - Voodoo5 seems to suffer from precision problems in some + * blend modes. To pass all the conformance tests we'd have to + * fall back to software for many modes. Revisit someday. + */ +} + +static void tdfxDDBlendFuncSeparate( GLcontext *ctx, + GLenum sfactorRGB, GLenum dfactorRGB, + GLenum sfactorA, GLenum dfactorA ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_ALPHA; +} + +/* ============================================================= + * Stipple + */ + +void tdfxUpdateStipple( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + GrStippleMode_t mode = GR_STIPPLE_DISABLE; + + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s()\n", __FUNCTION__ ); + } + + FLUSH_BATCH( fxMesa ); + + if (ctx->Polygon.StippleFlag) { + mode = GR_STIPPLE_PATTERN; + } + + if ( fxMesa->Stipple.Mode != mode ) { + fxMesa->Stipple.Mode = mode; + fxMesa->dirty |= TDFX_UPLOAD_STIPPLE; + } +} + + +/* ============================================================= + * Depth testing + */ + +static void tdfxUpdateZMode( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + GrCmpFnc_t func; + FxI32 bias; + FxBool mask; + + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) + fprintf( stderr, "%s()\n", __FUNCTION__ ); + + + bias = (FxI32) (ctx->Polygon.OffsetUnits * TDFX_DEPTH_BIAS_SCALE); + + if ( ctx->Depth.Test ) { + switch ( ctx->Depth.Func ) { + case GL_NEVER: + func = GR_CMP_NEVER; + break; + case GL_LESS: + func = GR_CMP_LESS; + break; + case GL_LEQUAL: + func = GR_CMP_LEQUAL; + break; + case GL_EQUAL: + func = GR_CMP_EQUAL; + break; + case GL_GEQUAL: + func = GR_CMP_GEQUAL; + break; + case GL_GREATER: + func = GR_CMP_GREATER; + break; + case GL_NOTEQUAL: + func = GR_CMP_NOTEQUAL; + break; + case GL_ALWAYS: + default: + func = GR_CMP_ALWAYS; + break; + } + + if ( ctx->Depth.Mask ) { + mask = FXTRUE; + } + else { + mask = FXFALSE; + } + } + else { + /* depth testing disabled */ + func = GR_CMP_ALWAYS; /* fragments always pass */ + mask = FXFALSE; /* zbuffer is not touched */ + } + + fxMesa->Depth.Clear = (FxU32) (((1 << fxMesa->glCtx->Visual.depthBits) - 1) + * ctx->Depth.Clear); + + if ( fxMesa->Depth.Bias != bias ) { + fxMesa->Depth.Bias = bias; + fxMesa->dirty |= TDFX_UPLOAD_DEPTH_BIAS; + } + if ( fxMesa->Depth.Func != func ) { + fxMesa->Depth.Func = func; + fxMesa->dirty |= TDFX_UPLOAD_DEPTH_FUNC | TDFX_UPLOAD_DEPTH_MASK; + } + if ( fxMesa->Depth.Mask != mask ) { + fxMesa->Depth.Mask = mask; + fxMesa->dirty |= TDFX_UPLOAD_DEPTH_MASK; + } +} + +static void tdfxDDDepthFunc( GLcontext *ctx, GLenum func ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_DEPTH; +} + +static void tdfxDDDepthMask( GLcontext *ctx, GLboolean flag ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_DEPTH; +} + +static void tdfxDDClearDepth( GLcontext *ctx, GLclampd d ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_DEPTH; +} + + + +/* ============================================================= + * Stencil + */ + + +/* Evaluate all stencil state and make the Glide calls. + */ +static GrStencil_t convertGLStencilOp( GLenum op ) +{ + switch ( op ) { + case GL_KEEP: + return GR_STENCILOP_KEEP; + case GL_ZERO: + return GR_STENCILOP_ZERO; + case GL_REPLACE: + return GR_STENCILOP_REPLACE; + case GL_INCR: + return GR_STENCILOP_INCR_CLAMP; + case GL_DECR: + return GR_STENCILOP_DECR_CLAMP; + case GL_INVERT: + return GR_STENCILOP_INVERT; + case GL_INCR_WRAP_EXT: + return GR_STENCILOP_INCR_WRAP; + case GL_DECR_WRAP_EXT: + return GR_STENCILOP_DECR_WRAP; + default: + _mesa_problem( NULL, "bad stencil op in convertGLStencilOp" ); + } + return GR_STENCILOP_KEEP; /* never get, silence compiler warning */ +} + + +static void tdfxUpdateStencil( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s()\n", __FUNCTION__ ); + } + + if (fxMesa->haveHwStencil) { + if (ctx->Stencil.Enabled) { + fxMesa->Stencil.Function = ctx->Stencil.Function[0] - GL_NEVER; + fxMesa->Stencil.RefValue = ctx->Stencil.Ref[0]; + fxMesa->Stencil.ValueMask = ctx->Stencil.ValueMask[0]; + fxMesa->Stencil.WriteMask = ctx->Stencil.WriteMask[0]; + fxMesa->Stencil.FailFunc = convertGLStencilOp(ctx->Stencil.FailFunc[0]); + fxMesa->Stencil.ZFailFunc = convertGLStencilOp(ctx->Stencil.ZFailFunc[0]); + fxMesa->Stencil.ZPassFunc = convertGLStencilOp(ctx->Stencil.ZPassFunc[0]); + fxMesa->Stencil.Clear = ctx->Stencil.Clear & 0xff; + } + fxMesa->dirty |= TDFX_UPLOAD_STENCIL; + } +} + + +static void tdfxDDStencilFunc( GLcontext *ctx, GLenum func, + GLint ref, GLuint mask ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_STENCIL; +} + +static void tdfxDDStencilMask( GLcontext *ctx, GLuint mask ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_STENCIL; +} + +static void tdfxDDStencilOp( GLcontext *ctx, GLenum sfail, + GLenum zfail, GLenum zpass ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_STENCIL; +} + + +/* ============================================================= + * Fog - orthographic fog still not working + */ + +static void tdfxUpdateFogAttrib( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + GrFogMode_t mode; + GrColor_t color; + + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s()\n", __FUNCTION__ ); + } + + if ( ctx->Fog.Enabled ) { + mode = GR_FOG_WITH_TABLE_ON_Q; + } else { + mode = GR_FOG_DISABLE; + } + + color = TDFXPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F), + (GLubyte)(ctx->Fog.Color[1]*255.0F), + (GLubyte)(ctx->Fog.Color[2]*255.0F)); + + if ( fxMesa->Fog.Mode != mode ) { + fxMesa->Fog.Mode = mode; + fxMesa->dirty |= TDFX_UPLOAD_FOG_MODE; + } + if ( fxMesa->Fog.Color != color ) { + fxMesa->Fog.Color = color; + fxMesa->dirty |= TDFX_UPLOAD_FOG_COLOR; + } + if ( fxMesa->Fog.TableMode != ctx->Fog.Mode || + fxMesa->Fog.Density != ctx->Fog.Density || + fxMesa->Fog.Near != ctx->Fog.Start || + fxMesa->Fog.Far != ctx->Fog.End ) + { + switch( ctx->Fog.Mode ) { + case GL_EXP: + fxMesa->Glide.guFogGenerateExp( fxMesa->Fog.Table, ctx->Fog.Density ); + break; + case GL_EXP2: + fxMesa->Glide.guFogGenerateExp2( fxMesa->Fog.Table, ctx->Fog.Density); + break; + case GL_LINEAR: + fxMesa->Glide.guFogGenerateLinear( fxMesa->Fog.Table, + ctx->Fog.Start, ctx->Fog.End ); + break; + } + + fxMesa->Fog.TableMode = ctx->Fog.Mode; + fxMesa->Fog.Density = ctx->Fog.Density; + fxMesa->Fog.Near = ctx->Fog.Start; + fxMesa->Fog.Far = ctx->Fog.End; + fxMesa->dirty |= TDFX_UPLOAD_FOG_TABLE; + } +} + +static void tdfxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_FOG; +} + + +/* ============================================================= + * Clipping + */ + +static int intersect_rect( XF86DRIClipRectPtr out, + const XF86DRIClipRectPtr a, + const XF86DRIClipRectPtr b) +{ + *out = *a; + if (b->x1 > out->x1) out->x1 = b->x1; + if (b->y1 > out->y1) out->y1 = b->y1; + if (b->x2 < out->x2) out->x2 = b->x2; + if (b->y2 < out->y2) out->y2 = b->y2; + if (out->x1 >= out->x2) return 0; + if (out->y1 >= out->y2) return 0; + return 1; +} + + +/* + * Examine XF86 cliprect list and scissor state to recompute our + * cliprect list. + */ +void tdfxUpdateClipping( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + __DRIdrawablePrivate *dPriv = fxMesa->driDrawable; + + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s()\n", __FUNCTION__ ); + } + + assert(ctx); + assert(fxMesa); + assert(dPriv); + + if ( dPriv->x != fxMesa->x_offset || dPriv->y != fxMesa->y_offset || + dPriv->w != fxMesa->width || dPriv->h != fxMesa->height ) { + fxMesa->x_offset = dPriv->x; + fxMesa->y_offset = dPriv->y; + fxMesa->width = dPriv->w; + fxMesa->height = dPriv->h; + fxMesa->y_delta = + fxMesa->screen_height - fxMesa->y_offset - fxMesa->height; + tdfxUpdateViewport( ctx ); + } + + if (fxMesa->scissoredClipRects && fxMesa->pClipRects) { + free(fxMesa->pClipRects); + } + + if (ctx->Scissor.Enabled) { + /* intersect OpenGL scissor box with all cliprects to make a new + * list of cliprects. + */ + XF86DRIClipRectRec scissor; + int x1 = ctx->Scissor.X + fxMesa->x_offset; + int y1 = fxMesa->screen_height - fxMesa->y_delta + - ctx->Scissor.Y - ctx->Scissor.Height; + int x2 = x1 + ctx->Scissor.Width; + int y2 = y1 + ctx->Scissor.Height; + scissor.x1 = MAX2(x1, 0); + scissor.y1 = MAX2(y1, 0); + scissor.x2 = MAX2(x2, 0); + scissor.y2 = MAX2(y2, 0); + + assert(scissor.x2 >= scissor.x1); + assert(scissor.y2 >= scissor.y1); + + fxMesa->pClipRects = malloc(dPriv->numClipRects + * sizeof(XF86DRIClipRectRec)); + if (fxMesa->pClipRects) { + int i; + fxMesa->numClipRects = 0; + for (i = 0; i < dPriv->numClipRects; i++) { + if (intersect_rect(&fxMesa->pClipRects[fxMesa->numClipRects], + &scissor, &dPriv->pClipRects[i])) { + fxMesa->numClipRects++; + } + } + fxMesa->scissoredClipRects = GL_TRUE; + } + else { + /* out of memory, forgo scissor */ + fxMesa->numClipRects = dPriv->numClipRects; + fxMesa->pClipRects = dPriv->pClipRects; + fxMesa->scissoredClipRects = GL_FALSE; + } + } + else { + fxMesa->numClipRects = dPriv->numClipRects; + fxMesa->pClipRects = dPriv->pClipRects; + fxMesa->scissoredClipRects = GL_FALSE; + } + + fxMesa->dirty |= TDFX_UPLOAD_CLIP; +} + + + +/* ============================================================= + * Culling + */ + +void tdfxUpdateCull( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + GrCullMode_t mode = GR_CULL_DISABLE; + + /* KW: don't need to check raster_primitive here as we don't + * attempt to draw lines or points with triangles. + */ + if ( ctx->Polygon.CullFlag ) { + switch ( ctx->Polygon.CullFaceMode ) { + case GL_FRONT: + if ( ctx->Polygon.FrontFace == GL_CCW ) { + mode = GR_CULL_POSITIVE; + } else { + mode = GR_CULL_NEGATIVE; + } + break; + + case GL_BACK: + if ( ctx->Polygon.FrontFace == GL_CCW ) { + mode = GR_CULL_NEGATIVE; + } else { + mode = GR_CULL_POSITIVE; + } + break; + + case GL_FRONT_AND_BACK: + /* Handled as a fallback on triangles in tdfx_tris.c */ + return; + + default: + ASSERT(0); + break; + } + } + + if ( fxMesa->CullMode != mode ) { + fxMesa->CullMode = mode; + fxMesa->dirty |= TDFX_UPLOAD_CULL; + } +} + +static void tdfxDDCullFace( GLcontext *ctx, GLenum mode ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_CULL; +} + +static void tdfxDDFrontFace( GLcontext *ctx, GLenum mode ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_CULL; +} + + +/* ============================================================= + * Line drawing. + */ + +static void tdfxUpdateLine( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s()\n", __FUNCTION__ ); + } + + FLUSH_BATCH( fxMesa ); + fxMesa->dirty |= TDFX_UPLOAD_LINE; +} + + +static void tdfxDDLineWidth( GLcontext *ctx, GLfloat width ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_LINE; +} + + +/* ============================================================= + * Color Attributes + */ + +static void tdfxDDColorMask( GLcontext *ctx, + GLboolean r, GLboolean g, + GLboolean b, GLboolean a ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + + FLUSH_BATCH( fxMesa ); + + if ( fxMesa->Color.ColorMask[RCOMP] != r || + fxMesa->Color.ColorMask[GCOMP] != g || + fxMesa->Color.ColorMask[BCOMP] != b || + fxMesa->Color.ColorMask[ACOMP] != a ) { + fxMesa->Color.ColorMask[RCOMP] = r; + fxMesa->Color.ColorMask[GCOMP] = g; + fxMesa->Color.ColorMask[BCOMP] = b; + fxMesa->Color.ColorMask[ACOMP] = a; + fxMesa->dirty |= TDFX_UPLOAD_COLOR_MASK; + + if (ctx->Visual.redBits < 8) { + /* Can't do RGB colormasking in 16bpp mode. */ + /* We can completely ignore the alpha mask. */ + FALLBACK( fxMesa, TDFX_FALLBACK_COLORMASK, (r != g || g != b) ); + } + } +} + + +static void tdfxDDClearColor( GLcontext *ctx, + const GLfloat color[4] ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + GLubyte c[4]; + FLUSH_BATCH( fxMesa ); + CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); + CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); + CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); + CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); + fxMesa->Color.ClearColor = TDFXPACKCOLOR888( c[0], c[1], c[2] ); + fxMesa->Color.ClearAlpha = c[3]; +} + + +/* ============================================================= + * Light Model + */ + +static void tdfxDDLightModelfv( GLcontext *ctx, GLenum pname, + const GLfloat *param ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + + if ( pname == GL_LIGHT_MODEL_COLOR_CONTROL ) { + FALLBACK( fxMesa, TDFX_FALLBACK_SPECULAR, + (ctx->Light.Enabled && + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR )); + } +} + +static void tdfxDDShadeModel( GLcontext *ctx, GLenum mode ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + + /* FIXME: Can we implement native flat shading? */ + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_TEXTURE; +} + + +/* ============================================================= + * Scissor + */ + +static void +tdfxDDScissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_CLIP; +} + +/* ============================================================= + * Render + */ + +static void tdfxUpdateRenderAttrib( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + FLUSH_BATCH( fxMesa ); + fxMesa->dirty |= TDFX_UPLOAD_RENDER_BUFFER; +} + +/* ============================================================= + * Viewport + */ + +void tdfxUpdateViewport( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + const GLfloat *v = ctx->Viewport._WindowMap.m; + GLfloat *m = fxMesa->hw_viewport; + + m[MAT_SX] = v[MAT_SX]; + m[MAT_TX] = v[MAT_TX] + fxMesa->x_offset + TRI_X_OFFSET; + m[MAT_SY] = v[MAT_SY]; + m[MAT_TY] = v[MAT_TY] + fxMesa->y_delta + TRI_Y_OFFSET; + m[MAT_SZ] = v[MAT_SZ]; + m[MAT_TZ] = v[MAT_TZ]; + + fxMesa->SetupNewInputs |= VERT_BIT_CLIP; +} + + +static void tdfxDDViewport( GLcontext *ctx, GLint x, GLint y, + GLsizei w, GLsizei h ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_VIEWPORT; +} + + +static void tdfxDDDepthRange( GLcontext *ctx, GLclampd nearVal, GLclampd farVal ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_VIEWPORT; +} + + +/* ============================================================= + * State enable/disable + */ + +static void tdfxDDEnable( GLcontext *ctx, GLenum cap, GLboolean state ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx ); + + switch ( cap ) { + case GL_ALPHA_TEST: + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_ALPHA; + break; + + case GL_BLEND: + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_ALPHA; + FALLBACK( fxMesa, TDFX_FALLBACK_LOGICOP, + (ctx->Color.ColorLogicOpEnabled && + ctx->Color.LogicOp != GL_COPY)); + break; + + case GL_CULL_FACE: + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_CULL; + break; + + case GL_DEPTH_TEST: + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_DEPTH; + break; + + case GL_DITHER: + FLUSH_BATCH( fxMesa ); + if ( state ) { + fxMesa->Color.Dither = GR_DITHER_2x2; + } else { + fxMesa->Color.Dither = GR_DITHER_DISABLE; + } + fxMesa->dirty |= TDFX_UPLOAD_DITHER; + break; + + case GL_FOG: + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_FOG; + break; + + case GL_COLOR_LOGIC_OP: + FALLBACK( fxMesa, TDFX_FALLBACK_LOGICOP, + (ctx->Color.ColorLogicOpEnabled && + ctx->Color.LogicOp != GL_COPY)); + break; + + case GL_LIGHTING: + FALLBACK( fxMesa, TDFX_FALLBACK_SPECULAR, + (ctx->Light.Enabled && + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR )); + break; + + case GL_LINE_SMOOTH: + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_LINE; + break; + + case GL_LINE_STIPPLE: + FALLBACK(fxMesa, TDFX_FALLBACK_LINE_STIPPLE, state); + break; + + case GL_POLYGON_STIPPLE: + FLUSH_BATCH(fxMesa); + fxMesa->new_state |= TDFX_NEW_STIPPLE; + break; + + case GL_SCISSOR_TEST: + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_CLIP; + break; + + case GL_STENCIL_TEST: + FLUSH_BATCH( fxMesa ); + FALLBACK( fxMesa, TDFX_FALLBACK_STENCIL, state && !fxMesa->haveHwStencil); + break; + + case GL_TEXTURE_1D: + case GL_TEXTURE_3D: + FLUSH_BATCH( fxMesa ); + FALLBACK( fxMesa, TDFX_FALLBACK_TEXTURE_1D_3D, state); /* wrong */ + fxMesa->new_state |= TDFX_NEW_TEXTURE; + break; + + case GL_TEXTURE_2D: + FLUSH_BATCH( fxMesa ); + fxMesa->new_state |= TDFX_NEW_TEXTURE; + break; + + default: + return; + } +} + + + +/* Set the buffer used for drawing */ +/* XXX support for separate read/draw buffers hasn't been tested */ +static void tdfxDDDrawBuffer( GLcontext *ctx, GLenum mode ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s()\n", __FUNCTION__ ); + } + + FLUSH_BATCH( fxMesa ); + + /* + * _DrawDestMask is easier to cope with than . + */ + switch ( ctx->Color._DrawDestMask ) { + case FRONT_LEFT_BIT: + fxMesa->DrawBuffer = fxMesa->ReadBuffer = GR_BUFFER_FRONTBUFFER; + fxMesa->new_state |= TDFX_NEW_RENDER; + FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_FALSE ); + break; + case BACK_LEFT_BIT: + fxMesa->DrawBuffer = fxMesa->ReadBuffer = GR_BUFFER_BACKBUFFER; + fxMesa->new_state |= TDFX_NEW_RENDER; + FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_FALSE ); + break; + case 0: + FX_grColorMaskv( ctx, false4 ); + FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_FALSE ); + break; + default: + FALLBACK( fxMesa, TDFX_FALLBACK_DRAW_BUFFER, GL_TRUE ); + break; + } + + /* We want to update the s/w rast state too so that tdfxDDSetBuffer() + * gets called. + */ + _swrast_DrawBuffer(ctx, mode); +} + + +static void tdfxDDReadBuffer( GLcontext *ctx, GLenum mode ) +{ + /* XXX ??? */ +} + + +/* ============================================================= + * Polygon stipple + */ + +static void tdfxDDPolygonStipple( GLcontext *ctx, const GLubyte *mask ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + const GLubyte *m = mask; + GLubyte q[4]; + int i,j,k; + GLboolean allBitsSet; + +/* int active = (ctx->Polygon.StippleFlag && */ +/* fxMesa->reduced_prim == GL_TRIANGLES); */ + + FLUSH_BATCH(fxMesa); + fxMesa->Stipple.Pattern = 0xffffffff; + fxMesa->dirty |= TDFX_UPLOAD_STIPPLE; + fxMesa->new_state |= TDFX_NEW_STIPPLE; + + /* Check if the stipple pattern is fully opaque. If so, use software + * rendering. This basically a trick to make sure the OpenGL conformance + * test passes. + */ + allBitsSet = GL_TRUE; + for (i = 0; i < 32; i++) { + if (((GLuint *) mask)[i] != 0xffffffff) { + allBitsSet = GL_FALSE; + break; + } + } + if (allBitsSet) { + fxMesa->haveHwStipple = GL_FALSE; + return; + } + + q[0] = mask[0]; + q[1] = mask[4]; + q[2] = mask[8]; + q[3] = mask[12]; + + for (k = 0 ; k < 8 ; k++) + for (j = 0 ; j < 4; j++) + for (i = 0 ; i < 4 ; i++,m++) { + if (*m != q[j]) { + fxMesa->haveHwStipple = GL_FALSE; + return; + } + } + + fxMesa->haveHwStipple = GL_TRUE; + fxMesa->Stipple.Pattern = ( (q[0] << 0) | + (q[1] << 8) | + (q[2] << 16) | + (q[3] << 24) ); +} + + + +static void tdfxDDRenderMode( GLcontext *ctx, GLenum mode ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + FALLBACK( fxMesa, TDFX_FALLBACK_RENDER_MODE, (mode != GL_RENDER) ); +} + + + +static void tdfxDDPrintState( const char *msg, GLuint flags ) +{ + fprintf( stderr, + "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s\n", + msg, + flags, + (flags & TDFX_NEW_COLOR) ? "color, " : "", + (flags & TDFX_NEW_ALPHA) ? "alpha, " : "", + (flags & TDFX_NEW_DEPTH) ? "depth, " : "", + (flags & TDFX_NEW_RENDER) ? "render, " : "", + (flags & TDFX_NEW_FOG) ? "fog, " : "", + (flags & TDFX_NEW_STENCIL) ? "stencil, " : "", + (flags & TDFX_NEW_STIPPLE) ? "stipple, " : "", + (flags & TDFX_NEW_CLIP) ? "clip, " : "", + (flags & TDFX_NEW_VIEWPORT) ? "viewport, " : "", + (flags & TDFX_NEW_CULL) ? "cull, " : "", + (flags & TDFX_NEW_GLIDE) ? "glide, " : "", + (flags & TDFX_NEW_TEXTURE) ? "texture, " : "", + (flags & TDFX_NEW_CONTEXT) ? "context, " : ""); +} + + + +void tdfxDDUpdateHwState( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + int new_state = fxMesa->new_state; + + if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { + fprintf( stderr, "%s()\n", __FUNCTION__ ); + } + + if ( new_state ) + { + FLUSH_BATCH( fxMesa ); + + fxMesa->new_state = 0; + + if ( 0 ) + tdfxDDPrintState( "tdfxUpdateHwState", new_state ); + + /* Update the various parts of the context's state. + */ + if ( new_state & TDFX_NEW_ALPHA ) { + tdfxUpdateAlphaMode( ctx ); + } + + if ( new_state & TDFX_NEW_DEPTH ) + tdfxUpdateZMode( ctx ); + + if ( new_state & TDFX_NEW_FOG ) + tdfxUpdateFogAttrib( ctx ); + + if ( new_state & TDFX_NEW_CLIP ) + tdfxUpdateClipping( ctx ); + + if ( new_state & TDFX_NEW_STIPPLE ) + tdfxUpdateStipple( ctx ); + + if ( new_state & TDFX_NEW_CULL ) + tdfxUpdateCull( ctx ); + + if ( new_state & TDFX_NEW_LINE ) + tdfxUpdateLine( ctx ); + + if ( new_state & TDFX_NEW_VIEWPORT ) + tdfxUpdateViewport( ctx ); + + if ( new_state & TDFX_NEW_RENDER ) + tdfxUpdateRenderAttrib( ctx ); + + if ( new_state & TDFX_NEW_STENCIL ) + tdfxUpdateStencil( ctx ); + + if ( new_state & TDFX_NEW_TEXTURE ) { + tdfxUpdateTextureState( ctx ); + } + else if ( new_state & TDFX_NEW_TEXTURE_BIND ) { + tdfxUpdateTextureBinding( ctx ); + } + } + + if ( 0 ) { + FxI32 bias = (FxI32) (ctx->Polygon.OffsetUnits * TDFX_DEPTH_BIAS_SCALE); + + if ( fxMesa->Depth.Bias != bias ) { + fxMesa->Depth.Bias = bias; + fxMesa->dirty |= TDFX_UPLOAD_DEPTH_BIAS; + } + } + + if ( fxMesa->dirty ) { + LOCK_HARDWARE( fxMesa ); + tdfxEmitHwStateLocked( fxMesa ); + UNLOCK_HARDWARE( fxMesa ); + } +} + + +static void tdfxDDInvalidateState( GLcontext *ctx, GLuint new_state ) +{ + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + TDFX_CONTEXT(ctx)->new_gl_state |= new_state; +} + + + +/* Initialize the context's Glide state mirror. These values will be + * used as Glide function call parameters when the time comes. + */ +void tdfxInitState( tdfxContextPtr fxMesa ) +{ + GLcontext *ctx = fxMesa->glCtx; + GLint i; + + fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_LOCAL; + fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_NONE; + fxMesa->ColorCombine.Local = GR_COMBINE_LOCAL_ITERATED; + fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_NONE; + fxMesa->ColorCombine.Invert = FXFALSE; + fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL; + fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE; + fxMesa->AlphaCombine.Local = GR_COMBINE_LOCAL_ITERATED; + fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE; + fxMesa->AlphaCombine.Invert = FXFALSE; + + fxMesa->ColorCombineExt.SourceA = GR_CMBX_ITRGB; + fxMesa->ColorCombineExt.ModeA = GR_FUNC_MODE_X; + fxMesa->ColorCombineExt.SourceB = GR_CMBX_ZERO; + fxMesa->ColorCombineExt.ModeB = GR_FUNC_MODE_ZERO; + fxMesa->ColorCombineExt.SourceC = GR_CMBX_ZERO; + fxMesa->ColorCombineExt.InvertC = FXTRUE; + fxMesa->ColorCombineExt.SourceD = GR_CMBX_ZERO; + fxMesa->ColorCombineExt.InvertD = FXFALSE; + fxMesa->ColorCombineExt.Shift = 0; + fxMesa->ColorCombineExt.Invert = FXFALSE; + fxMesa->AlphaCombineExt.SourceA = GR_CMBX_ITALPHA; + fxMesa->AlphaCombineExt.ModeA = GR_FUNC_MODE_X; + fxMesa->AlphaCombineExt.SourceB = GR_CMBX_ZERO; + fxMesa->AlphaCombineExt.ModeB = GR_FUNC_MODE_ZERO; + fxMesa->AlphaCombineExt.SourceC = GR_CMBX_ZERO; + fxMesa->AlphaCombineExt.InvertC = FXTRUE; + fxMesa->AlphaCombineExt.SourceD = GR_CMBX_ZERO; + fxMesa->AlphaCombineExt.InvertD = FXFALSE; + fxMesa->AlphaCombineExt.Shift = 0; + fxMesa->AlphaCombineExt.Invert = FXFALSE; + + fxMesa->sScale0 = fxMesa->tScale0 = 1.0; + fxMesa->sScale1 = fxMesa->tScale1 = 1.0; + + fxMesa->TexPalette.Type = 0; + fxMesa->TexPalette.Data = NULL; + + for ( i = 0 ; i < TDFX_NUM_TMU ; i++ ) { + fxMesa->TexSource[i].StartAddress = 0; + fxMesa->TexSource[i].EvenOdd = GR_MIPMAPLEVELMASK_EVEN; + fxMesa->TexSource[i].Info = NULL; + + fxMesa->TexCombine[i].FunctionRGB = 0; + fxMesa->TexCombine[i].FactorRGB = 0; + fxMesa->TexCombine[i].FunctionAlpha = 0; + fxMesa->TexCombine[i].FactorAlpha = 0; + fxMesa->TexCombine[i].InvertRGB = FXFALSE; + fxMesa->TexCombine[i].InvertAlpha = FXFALSE; + + fxMesa->TexCombineExt[i].Alpha.SourceA = 0; + /* XXX more state to init here */ + fxMesa->TexCombineExt[i].Color.SourceA = 0; + fxMesa->TexCombineExt[i].EnvColor = 0x0; + + fxMesa->TexParams[i].sClamp = GR_TEXTURECLAMP_WRAP; + fxMesa->TexParams[i].tClamp = GR_TEXTURECLAMP_WRAP; + fxMesa->TexParams[i].minFilt = GR_TEXTUREFILTER_POINT_SAMPLED; + fxMesa->TexParams[i].magFilt = GR_TEXTUREFILTER_BILINEAR; + fxMesa->TexParams[i].mmMode = GR_MIPMAP_DISABLE; + fxMesa->TexParams[i].LODblend = FXFALSE; + fxMesa->TexParams[i].LodBias = 0.0; + + fxMesa->TexState.EnvMode[i] = ~0; + fxMesa->TexState.TexFormat[i] = ~0; + fxMesa->TexState.Enabled[i] = 0; + } + + if ( ctx->Visual.doubleBufferMode) { + fxMesa->DrawBuffer = GR_BUFFER_BACKBUFFER; + fxMesa->ReadBuffer = GR_BUFFER_BACKBUFFER; + } else { + fxMesa->DrawBuffer = GR_BUFFER_FRONTBUFFER; + fxMesa->ReadBuffer = GR_BUFFER_FRONTBUFFER; + } + + fxMesa->Color.ClearColor = 0x00000000; + fxMesa->Color.ClearAlpha = 0x00; + fxMesa->Color.ColorMask[RCOMP] = FXTRUE; + fxMesa->Color.ColorMask[BCOMP] = FXTRUE; + fxMesa->Color.ColorMask[GCOMP] = FXTRUE; + fxMesa->Color.ColorMask[ACOMP] = FXTRUE; + fxMesa->Color.MonoColor = 0xffffffff; + + fxMesa->Color.AlphaFunc = GR_CMP_ALWAYS; + fxMesa->Color.AlphaRef = 0x00; + fxMesa->Color.BlendSrcRGB = GR_BLEND_ONE; + fxMesa->Color.BlendDstRGB = GR_BLEND_ZERO; + fxMesa->Color.BlendSrcA = GR_BLEND_ONE; + fxMesa->Color.BlendSrcA = GR_BLEND_ZERO; + + fxMesa->Color.Dither = GR_DITHER_2x2; + + if ( fxMesa->glCtx->Visual.depthBits > 0 ) { + fxMesa->Depth.Mode = GR_DEPTHBUFFER_ZBUFFER; + } else { + fxMesa->Depth.Mode = GR_DEPTHBUFFER_DISABLE; + } + fxMesa->Depth.Bias = 0; + fxMesa->Depth.Func = GR_CMP_LESS; + fxMesa->Depth.Clear = 0; /* computed later */ + fxMesa->Depth.Mask = FXTRUE; + + + fxMesa->Fog.Mode = GR_FOG_DISABLE; + fxMesa->Fog.Color = 0x00000000; + fxMesa->Fog.Table = NULL; + fxMesa->Fog.Density = 1.0; + fxMesa->Fog.Near = 1.0; + fxMesa->Fog.Far = 1.0; + + fxMesa->Stencil.Function = GR_CMP_ALWAYS; + fxMesa->Stencil.RefValue = 0; + fxMesa->Stencil.ValueMask = 0xff; + fxMesa->Stencil.WriteMask = 0xff; + fxMesa->Stencil.FailFunc = 0; + fxMesa->Stencil.ZFailFunc = 0; + fxMesa->Stencil.ZPassFunc = 0; + fxMesa->Stencil.Clear = 0; + + fxMesa->Stipple.Mode = GR_STIPPLE_DISABLE; + fxMesa->Stipple.Pattern = 0xffffffff; + + fxMesa->Scissor.minX = 0; + fxMesa->Scissor.minY = 0; + fxMesa->Scissor.maxX = 0; + fxMesa->Scissor.maxY = 0; + + fxMesa->Viewport.Mode = GR_WINDOW_COORDS; + fxMesa->Viewport.X = 0; + fxMesa->Viewport.Y = 0; + fxMesa->Viewport.Width = 0; + fxMesa->Viewport.Height = 0; + fxMesa->Viewport.Near = 0.0; + fxMesa->Viewport.Far = 0.0; + + fxMesa->CullMode = GR_CULL_DISABLE; + + fxMesa->Glide.ColorFormat = GR_COLORFORMAT_ABGR; + fxMesa->Glide.Origin = GR_ORIGIN_LOWER_LEFT; + fxMesa->Glide.Initialized = FXFALSE; +} + + + +void tdfxDDInitStateFuncs( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + + ctx->Driver.UpdateState = tdfxDDInvalidateState; + + + /* State notification callbacks: + */ + ctx->Driver.ClearIndex = NULL; + ctx->Driver.ClearColor = tdfxDDClearColor; + ctx->Driver.DrawBuffer = tdfxDDDrawBuffer; + ctx->Driver.ReadBuffer = tdfxDDReadBuffer; + + ctx->Driver.IndexMask = NULL; + ctx->Driver.ColorMask = tdfxDDColorMask; + + ctx->Driver.AlphaFunc = tdfxDDAlphaFunc; + ctx->Driver.BlendEquation = tdfxDDBlendEquation; + ctx->Driver.BlendFunc = tdfxDDBlendFunc; + ctx->Driver.BlendFuncSeparate = tdfxDDBlendFuncSeparate; + ctx->Driver.ClearDepth = tdfxDDClearDepth; + ctx->Driver.ClearStencil = NULL; + ctx->Driver.CullFace = tdfxDDCullFace; + ctx->Driver.FrontFace = tdfxDDFrontFace; + ctx->Driver.DepthFunc = tdfxDDDepthFunc; + ctx->Driver.DepthMask = tdfxDDDepthMask; + ctx->Driver.DepthRange = tdfxDDDepthRange; + ctx->Driver.Enable = tdfxDDEnable; + ctx->Driver.Fogfv = tdfxDDFogfv; + ctx->Driver.Hint = NULL; + ctx->Driver.Lightfv = NULL; + ctx->Driver.LightModelfv = tdfxDDLightModelfv; + ctx->Driver.LineStipple = NULL; + ctx->Driver.LineWidth = tdfxDDLineWidth; + ctx->Driver.PolygonStipple = tdfxDDPolygonStipple; + ctx->Driver.RenderMode = tdfxDDRenderMode; + ctx->Driver.Scissor = tdfxDDScissor; + ctx->Driver.ShadeModel = tdfxDDShadeModel; + + ctx->Driver.BindTexture = tdfxDDBindTexture; + ctx->Driver.DeleteTexture = tdfxDDDeleteTexture; + ctx->Driver.TexEnv = tdfxDDTexEnv; + ctx->Driver.TexParameter = tdfxDDTexParameter; + ctx->Driver.ChooseTextureFormat = tdfxDDChooseTextureFormat; + ctx->Driver.TexImage2D = tdfxDDTexImage2D; + ctx->Driver.TexSubImage2D = tdfxDDTexSubImage2D; + /* + ctx->Driver.TexImage2D = _mesa_store_teximage2d; + ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; + */ + + ctx->Driver.TexImage1D = _mesa_store_teximage1d; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; + ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; + ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; + ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; + ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + +/* ctx->Driver.GetTexImage = tdfxDDGetTexImage; */ + ctx->Driver.UpdateTexturePalette = tdfxDDTexturePalette; + + if ( fxMesa->haveHwStencil ) { + ctx->Driver.StencilFunc = tdfxDDStencilFunc; + ctx->Driver.StencilMask = tdfxDDStencilMask; + ctx->Driver.StencilOp = tdfxDDStencilOp; + } else { + ctx->Driver.StencilFunc = NULL; + ctx->Driver.StencilMask = NULL; + ctx->Driver.StencilOp = NULL; + } + + ctx->Driver.Viewport = tdfxDDViewport; + + + /* Swrast hooks for imaging extensions: + */ + ctx->Driver.CopyColorTable = _swrast_CopyColorTable; + ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; + ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; +} -- cgit v1.2.3