/* -*- 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. */ /* * New fixes: * Daniel Borca , 19 Jul 2004 * * Original rewrite: * Gareth Hughes , 29 Sep - 1 Oct 2000 * * Authors: * Gareth Hughes * Brian Paul * */ #include "tdfx_context.h" #include "tdfx_render.h" #include "tdfx_state.h" #include "tdfx_texman.h" #include "swrast/swrast.h" /* Clear the color and/or depth buffers. */ static void tdfxClear( struct gl_context *ctx, GLbitfield mask ) { tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx; GLbitfield softwareMask = mask & (BUFFER_BIT_ACCUM); const GLuint stencil_size = fxMesa->haveHwStencil ? fxMesa->glCtx->Visual.stencilBits : 0; if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "tdfxClear(0x%x)\n", mask); } /* Need this check to respond to glScissor and clipping updates */ if ((fxMesa->new_state & (TDFX_NEW_CLIP | TDFX_NEW_DEPTH)) || (fxMesa->dirty & TDFX_UPLOAD_COLOR_MASK)) { tdfxDDUpdateHwState(ctx); } /* we can't clear accum buffers */ mask &= ~(BUFFER_BIT_ACCUM); if (mask & BUFFER_BIT_STENCIL) { if (!fxMesa->haveHwStencil || (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { /* Napalm seems to have trouble with stencil write masks != 0xff */ /* do stencil clear in software */ mask &= ~(BUFFER_BIT_STENCIL); softwareMask |= BUFFER_BIT_STENCIL; } } if (fxMesa->glCtx->Visual.redBits != 8) { /* can only do color masking if running in 24/32bpp on Napalm */ if (ctx->Color.ColorMask[0][RCOMP] != ctx->Color.ColorMask[0][GCOMP] || ctx->Color.ColorMask[0][GCOMP] != ctx->Color.ColorMask[0][BCOMP]) { softwareMask |= (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)); mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT); } } if (fxMesa->haveHwStencil) { /* * If we want to clear stencil, it must be enabled * in the HW, even if the stencil test is not enabled * in the OGL state. */ LOCK_HARDWARE(fxMesa); if (mask & BUFFER_BIT_STENCIL) { fxMesa->Glide.grStencilMask(/*ctx->Stencil.WriteMask*/ 0xff); /* set stencil ref value = desired clear value */ fxMesa->Glide.grStencilFunc(GR_CMP_ALWAYS, (fxMesa->Stencil.Clear & 0xff), 0xff); fxMesa->Glide.grStencilOp(GR_STENCILOP_REPLACE, GR_STENCILOP_REPLACE, GR_STENCILOP_REPLACE); fxMesa->Glide.grEnable(GR_STENCIL_MODE_EXT); } else { fxMesa->Glide.grDisable(GR_STENCIL_MODE_EXT); } UNLOCK_HARDWARE(fxMesa); } /* * This may be ugly, but it's needed in order to work around a number * of Glide bugs. */ BEGIN_CLIP_LOOP(fxMesa); { /* * This could probably be done fancier but doing each possible case * explicitly is less error prone. */ switch (mask & ~BUFFER_BIT_STENCIL) { case BUFFER_BIT_BACK_LEFT | BUFFER_BIT_DEPTH: /* back buffer & depth */ FX_grColorMaskv_NoLock(ctx, true4); /* work around Voodoo3 bug */ fxMesa->Glide.grDepthMask(FXTRUE); fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER); if (stencil_size > 0) { fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); } else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear); if (!ctx->Depth.Mask || !ctx->Depth.Test) { fxMesa->Glide.grDepthMask(FXFALSE); } break; case BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_DEPTH: /* XXX it appears that the depth buffer isn't cleared when * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set. * This is a work-around/ */ /* clear depth */ fxMesa->Glide.grDepthMask(FXTRUE); fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER); FX_grColorMaskv_NoLock(ctx, false4); if (stencil_size > 0) fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear & 0xff); /* clear front */ FX_grColorMaskv_NoLock(ctx, true4); fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER); if (stencil_size > 0) fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear); if (!ctx->Depth.Mask || !ctx->Depth.Test) { fxMesa->Glide.grDepthMask(FXFALSE); } break; case BUFFER_BIT_BACK_LEFT: /* back buffer only */ fxMesa->Glide.grDepthMask(FXFALSE); fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER); if (stencil_size > 0) fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear); if (ctx->Depth.Mask && ctx->Depth.Test) { fxMesa->Glide.grDepthMask(FXTRUE); } break; case BUFFER_BIT_FRONT_LEFT: /* front buffer only */ fxMesa->Glide.grDepthMask(FXFALSE); fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER); if (stencil_size > 0) fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear); if (ctx->Depth.Mask && ctx->Depth.Test) { fxMesa->Glide.grDepthMask(FXTRUE); } break; case BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT: /* front and back */ fxMesa->Glide.grDepthMask(FXFALSE); fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER); if (stencil_size > 0) fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear); fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER); if (stencil_size > 0) fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear); if (ctx->Depth.Mask && ctx->Depth.Test) { fxMesa->Glide.grDepthMask(FXTRUE); } break; case BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT | BUFFER_BIT_DEPTH: /* clear front */ fxMesa->Glide.grDepthMask(FXFALSE); fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER); if (stencil_size > 0) fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear); /* clear back and depth */ fxMesa->Glide.grDepthMask(FXTRUE); fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER); if (stencil_size > 0) fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear); if (!ctx->Depth.Mask || !ctx->Depth.Mask) { fxMesa->Glide.grDepthMask(FXFALSE); } break; case BUFFER_BIT_DEPTH: /* just the depth buffer */ fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER); FX_grColorMaskv_NoLock(ctx, false4); fxMesa->Glide.grDepthMask(FXTRUE); if (stencil_size > 0) fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear); FX_grColorMaskv_NoLock(ctx, true4); if (ctx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER); if (!ctx->Depth.Test || !ctx->Depth.Mask) fxMesa->Glide.grDepthMask(FXFALSE); break; default: /* clear no color buffers or depth buffer but might clear stencil */ if (stencil_size > 0 && (mask & BUFFER_BIT_STENCIL)) { /* XXX need this RenderBuffer call to work around Glide bug */ fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER); fxMesa->Glide.grDepthMask(FXFALSE); FX_grColorMaskv_NoLock(ctx, false4); fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, (FxU32) (ctx->Stencil.Clear & 0xff)); if (ctx->Depth.Mask && ctx->Depth.Test) { fxMesa->Glide.grDepthMask(FXTRUE); } FX_grColorMaskv_NoLock(ctx, true4); if (ctx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER); } } } END_CLIP_LOOP(fxMesa); if (fxMesa->haveHwStencil && (mask & BUFFER_BIT_STENCIL)) { /* We changed the stencil state above. Signal that we need to * upload it again. */ fxMesa->dirty |= TDFX_UPLOAD_STENCIL; } if (softwareMask) _swrast_Clear(ctx, softwareMask); } static void tdfxFinish( struct gl_context *ctx ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); FLUSH_BATCH( fxMesa ); LOCK_HARDWARE( fxMesa ); fxMesa->Glide.grFinish(); UNLOCK_HARDWARE( fxMesa ); } static void tdfxFlush( struct gl_context *ctx ) { tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); FLUSH_BATCH( fxMesa ); LOCK_HARDWARE( fxMesa ); fxMesa->Glide.grFlush(); UNLOCK_HARDWARE( fxMesa ); } #if 0 static const char *texSource(int k) { switch (k) { case GR_CMBX_ZERO: return "GR_CMBX_ZERO"; case GR_CMBX_TEXTURE_ALPHA: return "GR_CMBX_TEXTURE_ALPHA"; case GR_CMBX_ALOCAL: return "GR_CMBX_ALOCAL"; case GR_CMBX_AOTHER: return "GR_CMBX_AOTHER"; case GR_CMBX_B: return "GR_CMBX_B"; case GR_CMBX_CONSTANT_ALPHA: return "GR_CMBX_CONSTANT_ALPHA"; case GR_CMBX_CONSTANT_COLOR: return "GR_CMBX_CONSTANT_COLOR"; case GR_CMBX_DETAIL_FACTOR: return "GR_CMBX_DETAIL_FACTOR"; case GR_CMBX_ITALPHA: return "GR_CMBX_ITALPHA"; case GR_CMBX_ITRGB: return "GR_CMBX_ITRGB"; case GR_CMBX_LOCAL_TEXTURE_ALPHA: return "GR_CMBX_LOCAL_TEXTURE_ALPHA"; case GR_CMBX_LOCAL_TEXTURE_RGB: return "GR_CMBX_LOCAL_TEXTURE_RGB"; case GR_CMBX_LOD_FRAC: return "GR_CMBX_LOD_FRAC"; case GR_CMBX_OTHER_TEXTURE_ALPHA: return "GR_CMBX_OTHER_TEXTURE_ALPHA"; case GR_CMBX_OTHER_TEXTURE_RGB: return "GR_CMBX_OTHER_TEXTURE_RGB"; case GR_CMBX_TEXTURE_RGB: return "GR_CMBX_TEXTURE_RGB"; case GR_CMBX_TMU_CALPHA: return "GR_CMBX_TMU_CALPHA"; case GR_CMBX_TMU_CCOLOR: return "GR_CMBX_TMU_CCOLOR"; default: return ""; } } #endif #if 0 static const char *texMode(int k) { switch (k) { case GR_FUNC_MODE_ZERO: return "GR_FUNC_MODE_ZERO"; case GR_FUNC_MODE_X: return "GR_FUNC_MODE_X"; case GR_FUNC_MODE_ONE_MINUS_X: return "GR_FUNC_MODE_ONE_MINUS_X"; case GR_FUNC_MODE_NEGATIVE_X: return "GR_FUNC_MODE_NEGATIVE_X"; case GR_FUNC_MODE_X_MINUS_HALF: return "GR_FUNC_MODE_X_MINUS_HALF"; default: return ""; } } #endif #if 0 static const char *texInvert(int k) { return k ? "FXTRUE" : "FXFALSE"; } #endif static void uploadTextureEnv( tdfxContextPtr fxMesa ) { if (TDFX_IS_NAPALM(fxMesa)) { int unit; for (unit = 0; unit < TDFX_NUM_TMU; unit++) { #if 0 printf("upload env %d\n", unit); printf(" cSourceA = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceA)); printf(" cModeA = %s\n", texMode(fxMesa->TexCombineExt[unit].Color.ModeA)); printf(" cSourceB = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceB)); printf(" cModeB = %s\n", texMode(fxMesa->TexCombineExt[unit].Color.ModeB)); printf(" cSourceC = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceC)); printf(" cInvertC = %s\n", texInvert(fxMesa->TexCombineExt[unit].Color.InvertC)); printf(" cSourceD = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceD)); printf(" cInvertD = %s\n", texInvert(fxMesa->TexCombineExt[unit].Color.InvertD)); printf(" cShift = %d\t", fxMesa->TexCombineExt[unit].Color.Shift); printf(" cInvert = %d\n", fxMesa->TexCombineExt[unit].Color.Invert); printf(" aSourceA = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceA)); printf(" aModeA = %s\n", texMode(fxMesa->TexCombineExt[unit].Alpha.ModeA)); printf(" aSourceB = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceB)); printf(" aModeB = %s\n", texMode(fxMesa->TexCombineExt[unit].Alpha.ModeB)); printf(" aSourceC = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceC)); printf(" aInvertC = %s\n", texInvert(fxMesa->TexCombineExt[unit].Alpha.InvertC)); printf(" aSourceD = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceD)); printf(" aInvertD = %s\n", texInvert(fxMesa->TexCombineExt[unit].Alpha.InvertD)); printf(" aShift = %d\t", fxMesa->TexCombineExt[unit].Alpha.Shift); printf(" aInvert = %d\n", fxMesa->TexCombineExt[unit].Alpha.Invert); printf(" Color = 0x%08x\n", fxMesa->TexCombineExt[unit].EnvColor); #endif fxMesa->Glide.grTexColorCombineExt(TDFX_TMU0 + unit, fxMesa->TexCombineExt[unit].Color.SourceA, fxMesa->TexCombineExt[unit].Color.ModeA, fxMesa->TexCombineExt[unit].Color.SourceB, fxMesa->TexCombineExt[unit].Color.ModeB, fxMesa->TexCombineExt[unit].Color.SourceC, fxMesa->TexCombineExt[unit].Color.InvertC, fxMesa->TexCombineExt[unit].Color.SourceD, fxMesa->TexCombineExt[unit].Color.InvertD, fxMesa->TexCombineExt[unit].Color.Shift, fxMesa->TexCombineExt[unit].Color.Invert); fxMesa->Glide.grTexAlphaCombineExt(TDFX_TMU0 + unit, fxMesa->TexCombineExt[unit].Alpha.SourceA, fxMesa->TexCombineExt[unit].Alpha.ModeA, fxMesa->TexCombineExt[unit].Alpha.SourceB, fxMesa->TexCombineExt[unit].Alpha.ModeB, fxMesa->TexCombineExt[unit].Alpha.SourceC, fxMesa->TexCombineExt[unit].Alpha.InvertC, fxMesa->TexCombineExt[unit].Alpha.SourceD, fxMesa->TexCombineExt[unit].Alpha.InvertD, fxMesa->TexCombineExt[unit].Alpha.Shift, fxMesa->TexCombineExt[unit].Alpha.Invert); fxMesa->Glide.grConstantColorValueExt(TDFX_TMU0 + unit, fxMesa->TexCombineExt[unit].EnvColor); } } else { /* Voodoo3 */ int unit; for (unit = 0; unit < TDFX_NUM_TMU; unit++) { struct tdfx_texcombine *comb = &fxMesa->TexCombine[unit]; fxMesa->Glide.grTexCombine(TDFX_TMU0 + unit, comb->FunctionRGB, comb->FactorRGB, comb->FunctionAlpha, comb->FactorAlpha, comb->InvertRGB, comb->InvertAlpha); } } } static void uploadTextureParams( tdfxContextPtr fxMesa ) { int unit; for (unit = 0; unit < TDFX_NUM_TMU; unit++) { const struct tdfx_texparams *p = &fxMesa->TexParams[unit]; /* printf("upload params %d\n", unit); printf(" clamp %x %x\n", env->sClamp, env->tClamp); printf(" filter %x %x\n", env->minFilt, env->magFilt); printf(" mipmap %x %x\n", env->mmMode, env->LODblend); printf(" lod bias %f\n", env->LodBias); */ fxMesa->Glide.grTexClampMode(GR_TMU0 + unit, p->sClamp, p->tClamp); fxMesa->Glide.grTexFilterMode(GR_TMU0 + unit, p->minFilt, p->magFilt); fxMesa->Glide.grTexMipMapMode(GR_TMU0 + unit, p->mmMode, p->LODblend); fxMesa->Glide.grTexLodBiasValue(GR_TMU0 + unit, CLAMP(p->LodBias, -8, 7.75)); } } static void uploadTextureSource( tdfxContextPtr fxMesa ) { int unit; for (unit = 0; unit < TDFX_NUM_TMU; unit++) { const struct tdfx_texsource *src = &fxMesa->TexSource[unit]; /* printf("upload source %d @ %d %p\n", unit, src->StartAddress, src->Info); */ if (src->Info) { /* printf(" smallLodLog2=%d largeLodLog2=%d ar=%d format=%d data=%p\n", src->Info->smallLodLog2, src->Info->largeLodLog2, src->Info->aspectRatioLog2, src->Info->format, src->Info->data); */ fxMesa->Glide.grTexSource(GR_TMU0 + unit, src->StartAddress, src->EvenOdd, src->Info); } } } static void uploadTextureImages( tdfxContextPtr fxMesa ) { struct gl_context *ctx = fxMesa->glCtx; int unit; for (unit = 0; unit < TDFX_NUM_TMU; unit++) { if (ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) { struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj); if (ti && ti->reloadImages && ti->whichTMU != TDFX_TMU_NONE) { /* printf("download texture image on unit %d\n", unit); */ tdfxTMDownloadTexture(fxMesa, tObj); ti->reloadImages = GL_FALSE; } } } } /* * If scissoring is enabled, compute intersection of scissor region * with all X clip rects, resulting in new cliprect list. * If number of cliprects is zero or one, call grClipWindow to setup * the clip region. Otherwise we'll call grClipWindow inside the * BEGIN_CLIP_LOOP macro. */ void tdfxUploadClipping( tdfxContextPtr fxMesa ) { __DRIdrawable *dPriv = fxMesa->driDrawable; assert(dPriv); if (fxMesa->numClipRects == 0) { /* all drawing clipped away */ fxMesa->Glide.grClipWindow(0, 0, 0, 0); } else if (fxMesa->numClipRects == 1) { fxMesa->Glide.grClipWindow(fxMesa->pClipRects[0].x1, fxMesa->screen_height - fxMesa->pClipRects[0].y2, fxMesa->pClipRects[0].x2, fxMesa->screen_height - fxMesa->pClipRects[0].y1); } /* else, we'll do a cliprect loop around all drawing */ fxMesa->Glide.grDRIPosition( dPriv->x, dPriv->y, dPriv->w, dPriv->h, fxMesa->numClipRects, fxMesa->pClipRects ); } void tdfxEmitHwStateLocked( tdfxContextPtr fxMesa ) { if ( !fxMesa->dirty ) return; if ( fxMesa->dirty & TDFX_UPLOAD_COLOR_COMBINE ) { if (TDFX_IS_NAPALM(fxMesa)) { fxMesa->Glide.grColorCombineExt(fxMesa->ColorCombineExt.SourceA, fxMesa->ColorCombineExt.ModeA, fxMesa->ColorCombineExt.SourceB, fxMesa->ColorCombineExt.ModeB, fxMesa->ColorCombineExt.SourceC, fxMesa->ColorCombineExt.InvertC, fxMesa->ColorCombineExt.SourceD, fxMesa->ColorCombineExt.InvertD, fxMesa->ColorCombineExt.Shift, fxMesa->ColorCombineExt.Invert); } else { /* Voodoo 3 */ fxMesa->Glide.grColorCombine( fxMesa->ColorCombine.Function, fxMesa->ColorCombine.Factor, fxMesa->ColorCombine.Local, fxMesa->ColorCombine.Other, fxMesa->ColorCombine.Invert ); } fxMesa->dirty &= ~TDFX_UPLOAD_COLOR_COMBINE; } if ( fxMesa->dirty & TDFX_UPLOAD_ALPHA_COMBINE ) { if (TDFX_IS_NAPALM(fxMesa)) { fxMesa->Glide.grAlphaCombineExt(fxMesa->AlphaCombineExt.SourceA, fxMesa->AlphaCombineExt.ModeA, fxMesa->AlphaCombineExt.SourceB, fxMesa->AlphaCombineExt.ModeB, fxMesa->AlphaCombineExt.SourceC, fxMesa->AlphaCombineExt.InvertC, fxMesa->AlphaCombineExt.SourceD, fxMesa->AlphaCombineExt.InvertD, fxMesa->AlphaCombineExt.Shift, fxMesa->AlphaCombineExt.Invert); } else { /* Voodoo 3 */ fxMesa->Glide.grAlphaCombine( fxMesa->AlphaCombine.Function, fxMesa->AlphaCombine.Factor, fxMesa->AlphaCombine.Local, fxMesa->AlphaCombine.Other, fxMesa->AlphaCombine.Invert ); } fxMesa->dirty &= ~TDFX_UPLOAD_ALPHA_COMBINE; } if ( fxMesa->dirty & TDFX_UPLOAD_RENDER_BUFFER ) { fxMesa->Glide.grRenderBuffer( fxMesa->DrawBuffer ); fxMesa->dirty &= ~TDFX_UPLOAD_RENDER_BUFFER; } if ( fxMesa->dirty & TDFX_UPLOAD_STIPPLE) { fxMesa->Glide.grStipplePattern( fxMesa->Stipple.Pattern ); fxMesa->Glide.grStippleMode( fxMesa->Stipple.Mode ); fxMesa->dirty &= ~TDFX_UPLOAD_STIPPLE; } if ( fxMesa->dirty & TDFX_UPLOAD_ALPHA_TEST ) { fxMesa->Glide.grAlphaTestFunction( fxMesa->Color.AlphaFunc ); fxMesa->dirty &= ~TDFX_UPLOAD_ALPHA_TEST; } if ( fxMesa->dirty & TDFX_UPLOAD_ALPHA_REF ) { fxMesa->Glide.grAlphaTestReferenceValue( fxMesa->Color.AlphaRef ); fxMesa->dirty &= ~TDFX_UPLOAD_ALPHA_REF; } if ( fxMesa->dirty & TDFX_UPLOAD_BLEND_FUNC ) { if (fxMesa->Glide.grAlphaBlendFunctionExt) { fxMesa->Glide.grAlphaBlendFunctionExt( fxMesa->Color.BlendSrcRGB, fxMesa->Color.BlendDstRGB, fxMesa->Color.BlendEqRGB, fxMesa->Color.BlendSrcA, fxMesa->Color.BlendDstA, fxMesa->Color.BlendEqA ); } else { fxMesa->Glide.grAlphaBlendFunction( fxMesa->Color.BlendSrcRGB, fxMesa->Color.BlendDstRGB, fxMesa->Color.BlendSrcA, fxMesa->Color.BlendDstA ); } fxMesa->dirty &= ~TDFX_UPLOAD_BLEND_FUNC; } if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_MODE ) { fxMesa->Glide.grDepthBufferMode( fxMesa->Depth.Mode ); fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_MODE; } if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_BIAS ) { fxMesa->Glide.grDepthBiasLevel( fxMesa->Depth.Bias ); fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_BIAS; } if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_FUNC ) { fxMesa->Glide.grDepthBufferFunction( fxMesa->Depth.Func ); fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_FUNC; } if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_MASK ) { fxMesa->Glide.grDepthMask( fxMesa->Depth.Mask ); fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_MASK; } if ( fxMesa->dirty & TDFX_UPLOAD_DITHER) { fxMesa->Glide.grDitherMode( fxMesa->Color.Dither ); } if ( fxMesa->dirty & TDFX_UPLOAD_FOG_MODE ) { fxMesa->Glide.grFogMode( fxMesa->Fog.Mode ); fxMesa->dirty &= ~TDFX_UPLOAD_FOG_MODE; } if ( fxMesa->dirty & TDFX_UPLOAD_FOG_COLOR ) { fxMesa->Glide.grFogColorValue( fxMesa->Fog.Color ); fxMesa->dirty &= ~TDFX_UPLOAD_FOG_COLOR; } if ( fxMesa->dirty & TDFX_UPLOAD_FOG_TABLE ) { fxMesa->Glide.grFogTable( fxMesa->Fog.Table ); fxMesa->dirty &= ~TDFX_UPLOAD_FOG_TABLE; } if ( fxMesa->dirty & TDFX_UPLOAD_CULL ) { fxMesa->Glide.grCullMode( fxMesa->CullMode ); fxMesa->dirty &= ~TDFX_UPLOAD_CULL; } if ( fxMesa->dirty & TDFX_UPLOAD_CLIP ) { tdfxUploadClipping( fxMesa ); fxMesa->dirty &= ~TDFX_UPLOAD_CLIP; } if ( fxMesa->dirty & TDFX_UPLOAD_COLOR_MASK ) { if ( fxMesa->Glide.grColorMaskExt && fxMesa->glCtx->Visual.redBits == 8) { fxMesa->Glide.grColorMaskExt( fxMesa->Color.ColorMask[RCOMP], fxMesa->Color.ColorMask[GCOMP], fxMesa->Color.ColorMask[BCOMP], fxMesa->Color.ColorMask[ACOMP] ); } else { fxMesa->Glide.grColorMask( fxMesa->Color.ColorMask[RCOMP] || fxMesa->Color.ColorMask[GCOMP] || fxMesa->Color.ColorMask[BCOMP], /*fxMesa->Color.ColorMask[0][ACOMP]*/GL_FALSE/*[dBorca] no-no*/ ); } fxMesa->dirty &= ~TDFX_UPLOAD_COLOR_MASK; } if ( fxMesa->dirty & TDFX_UPLOAD_CONSTANT_COLOR ) { fxMesa->Glide.grConstantColorValue( fxMesa->Color.MonoColor ); fxMesa->dirty &= ~TDFX_UPLOAD_CONSTANT_COLOR; } if ( fxMesa->dirty & TDFX_UPLOAD_LINE ) { if (fxMesa->glCtx->Line.SmoothFlag && fxMesa->glCtx->Line.Width == 1.0) fxMesa->Glide.grEnable(GR_AA_ORDERED); else fxMesa->Glide.grDisable(GR_AA_ORDERED); fxMesa->dirty &= ~TDFX_UPLOAD_LINE; } if ( fxMesa->dirty & TDFX_UPLOAD_STENCIL ) { if (fxMesa->glCtx->Stencil._Enabled) { fxMesa->Glide.grEnable(GR_STENCIL_MODE_EXT); fxMesa->Glide.grStencilOp(fxMesa->Stencil.FailFunc, fxMesa->Stencil.ZFailFunc, fxMesa->Stencil.ZPassFunc); fxMesa->Glide.grStencilFunc(fxMesa->Stencil.Function, fxMesa->Stencil.RefValue, fxMesa->Stencil.ValueMask); fxMesa->Glide.grStencilMask(fxMesa->Stencil.WriteMask); } else { fxMesa->Glide.grDisable(GR_STENCIL_MODE_EXT); } fxMesa->dirty &= ~TDFX_UPLOAD_STENCIL; } if ( fxMesa->dirty & TDFX_UPLOAD_VERTEX_LAYOUT ) { fxMesa->Glide.grGlideSetVertexLayout( fxMesa->layout[fxMesa->vertexFormat] ); /* [dborca] enable fogcoord */ fxMesa->Glide.grVertexLayout(GR_PARAM_FOG_EXT, TDFX_FOG_OFFSET, fxMesa->Fog.Mode == GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); fxMesa->dirty &= ~TDFX_UPLOAD_VERTEX_LAYOUT; } if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_ENV ) { uploadTextureEnv(fxMesa); fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_ENV; } if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_PARAMS ) { uploadTextureParams(fxMesa); fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_PARAMS; } if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_PALETTE ) { if (fxMesa->TexPalette.Data) { fxMesa->Glide.grTexDownloadTable(fxMesa->TexPalette.Type, fxMesa->TexPalette.Data); } fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_PALETTE; } if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_SOURCE ) { uploadTextureSource(fxMesa); fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_SOURCE; } if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_IMAGES ) { uploadTextureImages(fxMesa); fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_IMAGES; } fxMesa->dirty = 0; } void tdfxInitRenderFuncs( struct dd_function_table *functions ) { functions->Clear = tdfxClear; functions->Finish = tdfxFinish; functions->Flush = tdfxFlush; }