809 lines
32 KiB
C
809 lines
32 KiB
C
/* -*- 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, GLboolean all,
|
|
GLint x, GLint y, GLint width, GLint height )
|
|
{
|
|
tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx;
|
|
GLbitfield softwareMask = mask & (DD_ACCUM_BIT);
|
|
const GLuint stencil_size =
|
|
fxMesa->haveHwStencil ? fxMesa->glCtx->Visual.stencilBits : 0;
|
|
|
|
if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
|
|
fprintf( stderr, "%s( %d, %d, %d, %d )\n",
|
|
__FUNCTION__, (int) x, (int) y, (int) width, (int) height );
|
|
}
|
|
|
|
/* 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 &= ~(DD_ACCUM_BIT);
|
|
|
|
if (mask & DD_STENCIL_BIT) {
|
|
if (!fxMesa->haveHwStencil || ctx->Stencil.WriteMask[0] != 0xff) {
|
|
/* Napalm seems to have trouble with stencil write masks != 0xff */
|
|
/* do stencil clear in software */
|
|
mask &= ~(DD_STENCIL_BIT);
|
|
softwareMask |= DD_STENCIL_BIT;
|
|
}
|
|
}
|
|
|
|
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 & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT));
|
|
mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
|
|
}
|
|
}
|
|
|
|
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 & DD_STENCIL_BIT) {
|
|
fxMesa->Glide.grStencilMask(/*ctx->Stencil.WriteMask*/ 0xff);
|
|
/* set stencil ref value = desired clear value */
|
|
fxMesa->Glide.grStencilFunc(GR_CMP_ALWAYS,
|
|
fxMesa->Stencil.Clear, 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 & ~DD_STENCIL_BIT) {
|
|
case DD_BACK_LEFT_BIT | DD_DEPTH_BIT:
|
|
/* 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);
|
|
}
|
|
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 DD_FRONT_LEFT_BIT | DD_DEPTH_BIT:
|
|
/* 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);
|
|
else
|
|
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
|
|
fxMesa->Color.ClearAlpha,
|
|
fxMesa->Depth.Clear);
|
|
/* 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);
|
|
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 DD_BACK_LEFT_BIT:
|
|
/* 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);
|
|
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 DD_FRONT_LEFT_BIT:
|
|
/* 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);
|
|
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 DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT:
|
|
/* 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);
|
|
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);
|
|
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 DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | DD_DEPTH_BIT:
|
|
/* 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);
|
|
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);
|
|
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 DD_DEPTH_BIT:
|
|
/* 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);
|
|
else
|
|
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
|
|
fxMesa->Color.ClearAlpha,
|
|
fxMesa->Depth.Clear);
|
|
FX_grColorMaskv_NoLock(ctx, true4);
|
|
if (ctx->Color._DrawDestMask & DD_FRONT_LEFT_BIT)
|
|
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 & DD_STENCIL_BIT)) {
|
|
/* 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);
|
|
if (ctx->Depth.Mask && ctx->Depth.Test) {
|
|
fxMesa->Glide.grDepthMask(FXTRUE);
|
|
}
|
|
FX_grColorMaskv_NoLock(ctx, true4);
|
|
if (ctx->Color._DrawDestMask & DD_FRONT_LEFT_BIT)
|
|
fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
|
|
}
|
|
}
|
|
}
|
|
END_CLIP_LOOP(fxMesa);
|
|
|
|
if (fxMesa->haveHwStencil && (mask & DD_STENCIL_BIT)) {
|
|
/* 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, all, x, y, width, height );
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
}
|