add GL_EXT_fog_coord support to radeon driver. No vtxfmt code (just uses fallback) yet. May cause a tcl fallback if fog coord is used together with separate specular lighting. Fog factors are precomputed and then submitted instead of the raw coords (chip limitation, same as on r200).

This commit is contained in:
Roland Scheidegger
2005-10-17 00:54:12 +00:00
parent dd5a86339f
commit 2d61d30117
10 changed files with 217 additions and 58 deletions

View File

@@ -1383,7 +1383,8 @@ Mesa Version History
- GL_EXT_timer_query extension
- r200: add support for GL_ATI_fragment_shader
- added fast XOR-mode line drawing optimization
- radeon: add support for all 3 tmus and cube maps
- radeon: add support for all 3 tmus, GL_ARB_texture_cube_map
and GL_EXT_fog_coord
Changes:
- removed GL_HP_occlusion_test (use GL_ARB_occlusion_query instead)
Bug fixes:

View File

@@ -66,6 +66,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define need_GL_ARB_multisample
#define need_GL_ARB_texture_compression
#define need_GL_EXT_blend_minmax
#define need_GL_EXT_fog_coord
#define need_GL_EXT_secondary_color
#include "extension_helper.h"
@@ -139,6 +140,7 @@ const struct dri_extension card_extensions[] =
{ "GL_ARB_texture_mirrored_repeat", NULL },
{ "GL_EXT_blend_logic_op", NULL },
{ "GL_EXT_blend_subtract", GL_EXT_blend_minmax_functions },
{ "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
{ "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
{ "GL_EXT_stencil_wrap", NULL },
{ "GL_EXT_texture_edge_clamp", NULL },
@@ -238,6 +240,9 @@ radeonCreateContext( const __GLcontextModes *glVisual,
if ( !rmesa )
return GL_FALSE;
/* init exp fog table data */
radeonInitStaticFogData();
/* Parse configuration files.
* Do this here so that initialMaxAnisotropy is set before we create
* the default textures.

View File

@@ -48,6 +48,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_state.h"
#include "radeon_swtcl.h"
#include "radeon_maos.h"
#include "radeon_tcl.h"
#if 0
/* Usage:
@@ -169,6 +170,46 @@ do { \
} while (0)
#endif
static void emit_vecfog( GLcontext *ctx,
struct radeon_dma_region *rvb,
char *data,
int stride,
int count )
{
int i;
GLfloat *out;
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s count %d stride %d\n",
__FUNCTION__, count, stride);
assert (!rvb->buf);
if (stride == 0) {
radeonAllocDmaRegion( rmesa, rvb, 4, 4 );
count = 1;
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = 0;
rvb->aos_size = 1;
}
else {
radeonAllocDmaRegion( rmesa, rvb, count * 4, 4 ); /* alignment? */
rvb->aos_start = GET_START(rvb);
rvb->aos_stride = 1;
rvb->aos_size = 1;
}
/* Emit the data
*/
out = (GLfloat *)(rvb->address + rvb->start);
for (i = 0; i < count; i++) {
out[0] = radeonComputeFogBlendFactor( ctx, *(GLfloat *)data );
out++;
data += stride;
}
}
static void emit_vec4( GLcontext *ctx,
struct radeon_dma_region *rvb,
@@ -525,6 +566,20 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
component[nr++] = &rmesa->tcl.spec;
}
if (inputs & VERT_BIT_FOG) {
if (!rmesa->tcl.fog.buf)
emit_vecfog( ctx,
&(rmesa->tcl.fog),
(char *)VB->FogCoordPtr->data,
VB->FogCoordPtr->stride,
count);
vfmt |= RADEON_CP_VC_FRMT_FPFOG;
component[nr++] = &rmesa->tcl.fog;
}
vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1|RADEON_TCL_VTX_Q2));
@@ -589,6 +644,9 @@ void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
if (newinputs & VERT_BIT_COLOR1)
radeonReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ );
if (newinputs & VERT_BIT_FOG)
radeonReleaseDmaRegion( rmesa, &rmesa->tcl.fog, __FUNCTION__ );
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
if (newinputs & VERT_BIT_TEX(unit))

View File

@@ -50,7 +50,6 @@ static void TAG(emit)( GLcontext *ctx,
GLuint rqcoordsnoswap = 0;
GLuint (*coord)[4];
GLuint coord_stride; /* object coordinates */
GLubyte dummy[4];
int i;
union emit_union *v = (union emit_union *)dest;
@@ -133,7 +132,7 @@ static void TAG(emit)( GLcontext *ctx,
}
}
if (DO_SPEC) {
if (DO_SPEC_OR_FOG) {
if (VB->SecondaryColorPtr[0]) {
spec = VB->SecondaryColorPtr[0]->data;
spec_stride = VB->SecondaryColorPtr[0]->stride;
@@ -143,12 +142,12 @@ static void TAG(emit)( GLcontext *ctx,
}
}
if (DO_FOG) {
if (DO_SPEC_OR_FOG) {
if (VB->FogCoordPtr) {
fog = VB->FogCoordPtr->data;
fog_stride = VB->FogCoordPtr->stride;
} else {
fog = (GLfloat (*)[4])&dummy; fog[0][0] = 0.0F;
fog = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_FOG];
fog_stride = 0;
}
}
@@ -202,7 +201,7 @@ static void TAG(emit)( GLcontext *ctx,
STRIDE_4F(col, col_stride);
v++;
}
if (DO_SPEC || DO_FOG) {
if (DO_SPEC_OR_FOG) {
if (DO_SPEC) {
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.red, spec[0][0]);
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.green, spec[0][1]);
@@ -210,8 +209,8 @@ static void TAG(emit)( GLcontext *ctx,
STRIDE_4F(spec, spec_stride);
}
if (DO_FOG) {
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.alpha, fog[0][0]);
fog = (GLfloat (*)[4])((GLubyte *)fog + fog_stride);
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.alpha, radeonComputeFogBlendFactor(ctx, fog[0][0]));
STRIDE_4F(fog, fog_stride);
}
if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
v++;
@@ -283,7 +282,7 @@ static void TAG(init)( void )
if (DO_W) sz++;
if (DO_NORM) sz += 3;
if (DO_RGBA) sz++;
if (DO_SPEC || DO_FOG) sz++;
if (DO_SPEC_OR_FOG) sz++;
if (DO_TEX0) sz += 2;
if (DO_TEX0 && DO_PTEX) sz++;
if (DO_TEX1) sz += 2;

View File

@@ -63,8 +63,11 @@ static struct {
#define DO_W (IND & RADEON_CP_VC_FRMT_W0)
#define DO_RGBA (IND & RADEON_CP_VC_FRMT_PKCOLOR)
#define DO_SPEC (IND & RADEON_CP_VC_FRMT_PKSPEC)
#define DO_FOG (IND & RADEON_CP_VC_FRMT_PKSPEC)
#define DO_SPEC_OR_FOG (IND & RADEON_CP_VC_FRMT_PKSPEC)
#define DO_SPEC ((IND & RADEON_CP_VC_FRMT_PKSPEC) && \
(ctx->_TriangleCaps & DD_SEPARATE_SPECULAR))
#define DO_FOG ((IND & RADEON_CP_VC_FRMT_PKSPEC) && ctx->Fog.Enabled && \
(ctx->Fog.FogCoordinateSource == GL_FOG_COORD))
#define DO_TEX0 (IND & RADEON_CP_VC_FRMT_ST0)
#define DO_TEX1 (IND & RADEON_CP_VC_FRMT_ST1)
#define DO_TEX2 (IND & RADEON_CP_VC_FRMT_ST2)
@@ -337,7 +340,7 @@ void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
req |= RADEON_CP_VC_FRMT_PKCOLOR;
}
if (inputs & VERT_BIT_COLOR1) {
if (inputs & (VERT_BIT_COLOR1|VERT_BIT_FOG)) {
req |= RADEON_CP_VC_FRMT_PKSPEC;
}

View File

@@ -55,6 +55,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "radeon_vtxfmt.h"
#include "drirenderbuffer.h"
static void radeonUpdateSpecular( GLcontext *ctx );
/* =============================================================
* Alpha blending
*/
@@ -329,9 +331,6 @@ static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
union { int i; float f; } c, d;
GLchan col[4];
c.i = rmesa->hw.fog.cmd[FOG_C];
d.i = rmesa->hw.fog.cmd[FOG_D];
switch (pname) {
case GL_FOG_MODE:
if (!ctx->Fog.Enabled)
@@ -341,30 +340,24 @@ static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
switch (ctx->Fog.Mode) {
case GL_LINEAR:
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR;
if (ctx->Fog.Start == ctx->Fog.End) {
c.f = 1.0F;
d.f = 1.0F;
}
else {
c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
}
break;
case GL_EXP:
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP;
c.f = 0.0;
d.f = ctx->Fog.Density;
break;
case GL_EXP2:
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2;
c.f = 0.0;
d.f = -(ctx->Fog.Density * ctx->Fog.Density);
break;
default:
return;
}
break;
/* fallthrough */
case GL_FOG_DENSITY:
case GL_FOG_START:
case GL_FOG_END:
if (!ctx->Fog.Enabled)
return;
c.i = rmesa->hw.fog.cmd[FOG_C];
d.i = rmesa->hw.fog.cmd[FOG_D];
switch (ctx->Fog.Mode) {
case GL_EXP:
c.f = 0.0;
@@ -374,13 +367,7 @@ static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
c.f = 0.0;
d.f = -(ctx->Fog.Density * ctx->Fog.Density);
break;
default:
break;
}
break;
case GL_FOG_START:
case GL_FOG_END:
if (ctx->Fog.Mode == GL_LINEAR) {
case GL_LINEAR:
if (ctx->Fog.Start == ctx->Fog.End) {
c.f = 1.0F;
d.f = 1.0F;
@@ -388,27 +375,29 @@ static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
}
break;
default:
break;
}
if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
RADEON_STATECHANGE( rmesa, fog );
rmesa->hw.fog.cmd[FOG_C] = c.i;
rmesa->hw.fog.cmd[FOG_D] = d.i;
}
break;
case GL_FOG_COLOR:
RADEON_STATECHANGE( rmesa, ctx );
UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] =
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~RADEON_FOG_COLOR_MASK;
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |=
radeonPackColor( 4, col[0], col[1], col[2], 0 );
break;
case GL_FOG_COORDINATE_SOURCE_EXT:
/* What to do?
*/
case GL_FOG_COORD_SRC:
radeonUpdateSpecular( ctx );
break;
default:
return;
}
if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
RADEON_STATECHANGE( rmesa, fog );
rmesa->hw.fog.cmd[FOG_C] = c.i;
rmesa->hw.fog.cmd[FOG_D] = d.i;
}
}
@@ -692,6 +681,7 @@ static void radeonUpdateSpecular( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
u_int32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
GLuint flag = 0;
RADEON_STATECHANGE( rmesa, tcl );
@@ -730,13 +720,22 @@ static void radeonUpdateSpecular( GLcontext *ctx )
}
if (ctx->Fog.Enabled) {
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
/* Bizzare: have to leave lighting enabled to get fog.
*/
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH) {
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
/* Bizzare: have to leave lighting enabled to get fog. */
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
}
else {
/* cannot do tcl fog factor calculation with fog coord source
* (send precomputed factors). Cannot use precomputed fog
* factors together with tcl spec light (need tcl fallback) */
flag = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &
RADEON_TCL_COMPUTE_SPECULAR) != 0;
}
}
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_FOGCOORDSPEC, flag);
if (NEED_SECONDARY_COLOR(ctx)) {
assert( (p & RADEON_SPECULAR_ENABLE) != 0 );
@@ -1809,8 +1808,6 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
}
radeonUpdateSpecular( ctx ); /* for PK_SPEC */
if (rmesa->TclFallback)
radeonChooseVertexState( ctx );
_mesa_allow_light_in_model( ctx, !state );
break;

View File

@@ -345,6 +345,7 @@ void radeonInitState( radeonContextPtr rmesa )
RADEON_RIGHT_HAND_CUBE_OGL */);
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (RADEON_FOG_VERTEX |
/* this bit unused for vertex fog */
RADEON_FOG_USE_DEPTH);
rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000;

View File

@@ -279,6 +279,88 @@ void radeonTclPrimitive( GLcontext *ctx,
}
}
/**********************************************************************/
/* Fog blend factor computation for hw tcl */
/* same calculation used as in t_vb_fog.c */
/**********************************************************************/
#define FOG_EXP_TABLE_SIZE 256
#define FOG_MAX (10.0)
#define EXP_FOG_MAX .0006595
#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
#if 1
#define NEG_EXP( result, narg ) \
do { \
GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR)); \
GLint k = (GLint) f; \
if (k > FOG_EXP_TABLE_SIZE-2) \
result = (GLfloat) EXP_FOG_MAX; \
else \
result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]); \
} while (0)
#else
#define NEG_EXP( result, narg ) \
do { \
result = exp(-narg); \
} while (0)
#endif
/**
* Initialize the exp_table[] lookup table for approximating exp().
*/
void
radeonInitStaticFogData( void )
{
GLfloat f = 0.0F;
GLint i = 0;
for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
exp_table[i] = (GLfloat) exp(-f);
}
}
/**
* Compute per-vertex fog blend factors from fog coordinates by
* evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function.
* Fog coordinates are distances from the eye (typically between the
* near and far clip plane distances).
* Note the fog (eye Z) coords may be negative so we use ABS(z) below.
* Fog blend factors are in the range [0,1].
*/
float
radeonComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord )
{
GLfloat end = ctx->Fog.End;
GLfloat d, temp;
const GLfloat z = FABSF(fogcoord);
switch (ctx->Fog.Mode) {
case GL_LINEAR:
if (ctx->Fog.Start == ctx->Fog.End)
d = 1.0F;
else
d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
temp = (end - z) * d;
return CLAMP(temp, 0.0F, 1.0F);
break;
case GL_EXP:
d = ctx->Fog.Density;
NEG_EXP( temp, d * z );
return temp;
break;
case GL_EXP2:
d = ctx->Fog.Density*ctx->Fog.Density;
NEG_EXP( temp, d * z * z );
return temp;
break;
default:
_mesa_problem(ctx, "Bad fog mode in make_fog_coord");
return 0;
}
}
/**********************************************************************/
/* Render pipeline stage */
@@ -314,7 +396,7 @@ static GLboolean radeon_run_tcl_render( GLcontext *ctx,
}
}
if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD ) {
if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) {
inputs |= VERT_BIT_FOG;
}
@@ -445,7 +527,8 @@ static char *fallbackStrings[] = {
"Texgen unit 0",
"Texgen unit 1",
"Texgen unit 2",
"User disable"
"User disable",
"Fogcoord with separate specular lighting"
};

View File

@@ -46,7 +46,10 @@ extern void radeonEmitPrimitive( GLcontext *ctx, GLuint first, GLuint last,
GLuint flags );
extern void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
extern void radeonInitStaticFogData( void );
extern float radeonComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord );
#define RADEON_TCL_FALLBACK_RASTER 0x1 /* rasterization */
#define RADEON_TCL_FALLBACK_UNFILLED 0x2 /* unfilled tris */
#define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE 0x4 /* twoside tris */
@@ -55,6 +58,7 @@ extern void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define RADEON_TCL_FALLBACK_TEXGEN_1 0x20 /* texgen, unit 1 */
#define RADEON_TCL_FALLBACK_TEXGEN_2 0x40 /* texgen, unit 2 */
#define RADEON_TCL_FALLBACK_TCL_DISABLE 0x80 /* user disable */
#define RADEON_TCL_FALLBACK_FOGCOORDSPEC 0x100 /* fogcoord, sep. spec light */
/* max maos_verts vertex format has a size of 18 floats */
#define RADEON_MAX_TCL_VERTSIZE (18*4)

View File

@@ -549,7 +549,8 @@ static GLboolean check_vtx_fmt( GLcontext *ctx )
GLuint ind = RADEON_CP_VC_FRMT_Z;
GLuint unit;
if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag)
if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag ||
(ctx->Fog.Enabled && (ctx->Fog.FogCoordinateSource == GL_FOG_COORD)))
return GL_FALSE;
if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
@@ -582,6 +583,10 @@ static GLboolean check_vtx_fmt( GLcontext *ctx )
}
}
if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD ) {
ind |= RADEON_CP_VC_FRMT_PKSPEC;
}
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
if (ctx->Texture.Unit[unit].TexGenEnabled) {
@@ -657,6 +662,9 @@ static GLboolean check_vtx_fmt( GLcontext *ctx )
UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->red, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] );
UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] );
UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->blue, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] );
/* fog ??? */
/* UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->alpha,
radeonComputeFogFactor(ctx->Current.Attrib[VERT_ATTRIB_FOG][0]) ); */
}
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
@@ -948,8 +956,6 @@ void radeonVtxfmtInit( GLcontext *ctx, GLboolean useCodegen )
/* Not active in supported states; just keep ctx->Current uptodate:
*/
vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT;
vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT;
vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
vfmt->Indexf = _mesa_noop_Indexf;
@@ -986,6 +992,8 @@ void radeonVtxfmtInit( GLcontext *ctx, GLboolean useCodegen )
vfmt->VertexAttrib3fvNV = radeon_fallback_VertexAttrib3fvNV;
vfmt->VertexAttrib4fNV = radeon_fallback_VertexAttrib4fNV;
vfmt->VertexAttrib4fvNV = radeon_fallback_VertexAttrib4fvNV;
vfmt->FogCoordfEXT = radeon_fallback_FogCoordfEXT;
vfmt->FogCoordfvEXT = radeon_fallback_FogCoordfvEXT;
(void)radeon_fallback_vtxfmt;