| /* -*- 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_render.c,v 1.4 2002/02/22 21:45:03 dawes Exp $ */ |
| |
| /* |
| * New fixes: |
| * Daniel Borca <dborca@users.sourceforge.net>, 19 Jul 2004 |
| * |
| * Original rewrite: |
| * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000 |
| * |
| * Authors: |
| * Gareth Hughes <gareth@valinux.com> |
| * Brian Paul <brianp@valinux.com> |
| * |
| */ |
| |
| #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( GLcontext *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[RCOMP] != ctx->Color.ColorMask[GCOMP] || |
| ctx->Color.ColorMask[GCOMP] != ctx->Color.ColorMask[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( GLcontext *ctx ) |
| { |
| tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); |
| |
| FLUSH_BATCH( fxMesa ); |
| |
| LOCK_HARDWARE( fxMesa ); |
| fxMesa->Glide.grFinish(); |
| UNLOCK_HARDWARE( fxMesa ); |
| } |
| |
| static void tdfxFlush( GLcontext *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 ) |
| { |
| GLcontext *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 ) |
| { |
| __DRIdrawablePrivate *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[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; |
| } |