From: Brian Paul Date: Fri, 15 Feb 2002 16:32:06 +0000 (+0000) Subject: Finished up GL_ARB_depth_texture and GL_ARB_shadow. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4182cf60d96a077a66675e89694529b5f9e4b329;p=mesa.git Finished up GL_ARB_depth_texture and GL_ARB_shadow. --- diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index ee8eb4f5383..8054360fd29 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -1,10 +1,10 @@ -/* $Id: extensions.c,v 1.68 2001/12/14 02:50:01 brianp Exp $ */ +/* $Id: extensions.c,v 1.69 2002/02/15 16:32:06 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2002 Brian Paul 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"), @@ -56,7 +56,7 @@ static struct { const char *name; int flag_offset; } default_extensions[] = { - { OFF, "GL_ARB_depth_texture", F(SGIX_depth_texture) }, + { OFF, "GL_ARB_depth_texture", F(ARB_depth_texture) }, { OFF, "GL_ARB_imaging", F(ARB_imaging) }, { OFF, "GL_ARB_multisample", F(ARB_multisample) }, { OFF, "GL_ARB_multitexture", F(ARB_multitexture) }, diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index a8a27ef3ed9..39f65940b5d 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -1,10 +1,10 @@ -/* $Id: texobj.c,v 1.51 2001/12/04 23:44:56 brianp Exp $ */ +/* $Id: texobj.c,v 1.52 2002/02/15 16:32:06 brianp Exp $ */ /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 4.1 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2002 Brian Paul 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"), @@ -84,7 +84,7 @@ _mesa_alloc_texture_object( struct gl_shared_state *shared, obj->CompareOperator = GL_TEXTURE_LEQUAL_R_SGIX; /* SGIX_shadow */ obj->CompareMode = GL_LUMINANCE; /* ARB_shadow */ obj->CompareFunc = GL_LEQUAL; /* ARB_shadow */ - obj->CompareResult = GL_LUMINANCE; /* ARB_shadow */ + obj->DepthMode = GL_LUMINANCE; /* ARB_depth_texture */ obj->ShadowAmbient = 0; /* ARB/SGIX_shadow_ambient */ _mesa_init_colortable(&obj->Palette); @@ -360,6 +360,11 @@ _mesa_test_texobj_completeness( const GLcontext *ctx, t->Complete = GL_FALSE; return; } + if (t->Image[i]->Format == GL_DEPTH_COMPONENT) { + t->Complete = GL_FALSE; + incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex"); + return; + } if (t->Image[i]->Width2 != width) { t->Complete = GL_FALSE; incomplete(t, "3D Image[i] bad width"); @@ -393,6 +398,12 @@ _mesa_test_texobj_completeness( const GLcontext *ctx, height /= 2; } if (i >= minLevel && i <= maxLevel) { + /* Don't support GL_DEPTH_COMPONENT for cube maps */ + if (t->Image[i]->Format == GL_DEPTH_COMPONENT) { + t->Complete = GL_FALSE; + incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex"); + return; + } /* check that we have images defined */ if (!t->Image[i] || !t->NegX[i] || !t->PosY[i] || !t->NegY[i] || diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c index a8c70f0a4c5..19e8984ad96 100644 --- a/src/mesa/main/texstate.c +++ b/src/mesa/main/texstate.c @@ -1,4 +1,4 @@ -/* $Id: texstate.c,v 1.63 2002/01/09 02:14:29 brianp Exp $ */ +/* $Id: texstate.c,v 1.64 2002/02/15 16:32:06 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -46,7 +46,6 @@ #ifndef GL_TEXTURE_COMPARE_MODE_ARB #define GL_TEXTURE_COMPARE_MODE_ARB 0x9990 #define GL_TEXTURE_COMPARE_FUNC_ARB 0x9991 -#define GL_TEXTURE_COMPARE_RESULT_ARB 0x9992 #define GL_COMPARE_R_TO_TEXTURE_ARB 0x9993 #endif @@ -1109,7 +1108,7 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params ) case GL_TEXTURE_COMPARE_MODE_ARB: if (ctx->Extensions.ARB_shadow) { const GLenum mode = (GLenum) params[0]; - if (mode == GL_LUMINANCE || mode == GL_COMPARE_R_TO_TEXTURE_ARB) { + if (mode == GL_NONE || mode == GL_COMPARE_R_TO_TEXTURE_ARB) { FLUSH_VERTICES(ctx, _NEW_TEXTURE); texObj->CompareMode = params[0]; } @@ -1144,23 +1143,23 @@ _mesa_TexParameterfv( GLenum target, GLenum pname, const GLfloat *params ) return; } break; - case GL_TEXTURE_COMPARE_RESULT_ARB: - if (ctx->Extensions.ARB_shadow) { + case GL_DEPTH_TEXTURE_MODE_ARB: + if (ctx->Extensions.ARB_depth_texture) { const GLenum result = (GLenum) params[0]; if (result == GL_LUMINANCE || result == GL_INTENSITY || result == GL_ALPHA) { FLUSH_VERTICES(ctx, _NEW_TEXTURE); - texObj->CompareResult = params[0]; + texObj->DepthMode = params[0]; } else { _mesa_error(ctx, GL_INVALID_ENUM, - "glTexParameter(bad GL_TEXTURE_COMPARE_RESULT_ARB)"); + "glTexParameter(bad GL_DEPTH_TEXTURE_MODE_ARB)"); return; } } else { _mesa_error(ctx, GL_INVALID_ENUM, - "glTexParameter(pname=GL_TEXTURE_COMPARE_RESULT_ARB)"); + "glTexParameter(pname=GL_DEPTH_TEXTURE_MODE_ARB)"); return; } break; @@ -1504,9 +1503,9 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) return; } break; - case GL_TEXTURE_COMPARE_RESULT_ARB: - if (ctx->Extensions.ARB_shadow) { - *params = (GLfloat) obj->CompareResult; + case GL_DEPTH_TEXTURE_MODE_ARB: + if (ctx->Extensions.ARB_depth_texture) { + *params = (GLfloat) obj->DepthMode; return; } break; @@ -1633,9 +1632,9 @@ _mesa_GetTexParameteriv( GLenum target, GLenum pname, GLint *params ) return; } break; - case GL_TEXTURE_COMPARE_RESULT_ARB: - if (ctx->Extensions.ARB_shadow) { - *params = (GLint) obj->CompareResult; + case GL_DEPTH_TEXTURE_MODE_ARB: + if (ctx->Extensions.ARB_depth_texture) { + *params = (GLint) obj->DepthMode; return; } break; diff --git a/src/mesa/swrast/s_texture.c b/src/mesa/swrast/s_texture.c index 206508559f0..0f1c5cdc968 100644 --- a/src/mesa/swrast/s_texture.c +++ b/src/mesa/swrast/s_texture.c @@ -1,4 +1,4 @@ -/* $Id: s_texture.c,v 1.50 2002/02/15 03:41:47 brianp Exp $ */ +/* $Id: s_texture.c,v 1.51 2002/02/15 16:32:06 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -1753,140 +1753,477 @@ sample_lambda_cube( GLcontext *ctx, GLuint texUnit, } +/* + * Sample a shadow/depth texture. + */ static void -null_sample_func( GLcontext *ctx, GLuint texUnit, - const struct gl_texture_object *tObj, GLuint n, - GLfloat texcoords[][4], const GLfloat lambda[], - GLchan rgba[][4]) +sample_depth_texture( GLcontext *ctx, GLuint unit, + const struct gl_texture_object *tObj, GLuint n, + GLfloat texcoords[][4], const GLfloat lambda[], + GLchan texel[][4] ) { -} + const GLint baseLevel = tObj->BaseLevel; + const struct gl_texture_image *texImage = tObj->Image[baseLevel]; + const GLuint width = texImage->Width; + const GLuint height = texImage->Height; + const GLchan ambient = tObj->ShadowAmbient; + GLboolean lequal, gequal; + GLchan result; + (void) unit; + ASSERT(tObj->Image[tObj->BaseLevel]->Format == GL_DEPTH_COMPONENT); + ASSERT(tObj->Dimensions == 1 || tObj->Dimensions == 2); -/**********************************************************************/ -/* Texture Sampling Setup */ -/**********************************************************************/ + /* XXXX if tObj->MinFilter != tObj->MagFilter, we're ignoring lambda */ + + /* XXX this could be precomputed and saved in the texture object */ + if (tObj->CompareFlag) { + /* GL_SGIX_shadow */ + if (tObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { + lequal = GL_TRUE; + gequal = GL_FALSE; + } + else { + ASSERT(tObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX); + lequal = GL_FALSE; + gequal = GL_TRUE; + } + } + else if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) { + /* GL_ARB_shadow */ + if (tObj->CompareFunc == GL_LEQUAL) { + lequal = GL_TRUE; + gequal = GL_FALSE; + } + else { + ASSERT(tObj->CompareFunc == GL_GEQUAL); + lequal = GL_FALSE; + gequal = GL_TRUE; + } + } + else { + lequal = gequal = GL_FALSE; + } + if (tObj->MagFilter == GL_NEAREST) { + GLuint i; + for (i = 0; i < n; i++) { + GLfloat depthSample; + GLint col, row; + COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapS, texcoords[i][0], width, col); + COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, texcoords[i][1], height, row); + depthSample = *((const GLfloat *) texImage->Data + row * width + col); -/* - * Setup the texture sampling function for this texture object. - */ -void -_swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit, - const struct gl_texture_object *t ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); + if (lequal) { + if (texcoords[i][2] <= depthSample) + result = CHAN_MAX; + else + result = ambient; + } + else if (gequal) { + if (texcoords[i][2] >= depthSample) + result = CHAN_MAX; + else + result = ambient; + } + else { + /* no comparison */ + CLAMPED_FLOAT_TO_CHAN(result, depthSample); + } - if (!t->Complete) { - swrast->TextureSample[texUnit] = null_sample_func; + switch (tObj->DepthMode) { + case GL_LUMINANCE: + texel[i][RCOMP] = result; + texel[i][GCOMP] = result; + texel[i][BCOMP] = result; + texel[i][ACOMP] = CHAN_MAX; + break; + case GL_INTENSITY: + texel[i][RCOMP] = result; + texel[i][GCOMP] = result; + texel[i][BCOMP] = result; + texel[i][ACOMP] = result; + break; + case GL_ALPHA: + texel[i][RCOMP] = 0; + texel[i][GCOMP] = 0; + texel[i][BCOMP] = 0; + texel[i][ACOMP] = result; + break; + default: + _mesa_problem(ctx, "Bad depth texture mode"); + } + } } else { - GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter); + GLuint i; + ASSERT(tObj->MagFilter == GL_LINEAR); + for (i = 0; i < n; i++) { + GLfloat depth00, depth01, depth10, depth11; + GLint i0, i1, j0, j1; + GLfloat u, v; + GLuint useBorderTexel; - if (needLambda) { - /* Compute min/mag filter threshold */ - if (t->MagFilter == GL_LINEAR - && (t->MinFilter == GL_NEAREST_MIPMAP_NEAREST || - t->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) { - swrast->_MinMagThresh[texUnit] = 0.5F; + COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapS, texcoords[i][0], u, width, i0, i1); + COMPUTE_LINEAR_TEXEL_LOCATIONS(tObj->WrapT, texcoords[i][1], v, height,j0, j1); + + useBorderTexel = 0; + if (texImage->Border) { + i0 += texImage->Border; + i1 += texImage->Border; + j0 += texImage->Border; + j1 += texImage->Border; } else { - swrast->_MinMagThresh[texUnit] = 0.0F; + if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT; + if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT; + if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT; + if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT; } - } - switch (t->Dimensions) { - case 1: - if (needLambda) { - swrast->TextureSample[texUnit] = sample_lambda_1d; - } - else if (t->MinFilter==GL_LINEAR) { - swrast->TextureSample[texUnit] = sample_linear_1d; + /* get four depth samples from the texture */ + if (useBorderTexel & (I0BIT | J0BIT)) { + depth00 = 1.0; + } + else { + depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0); + } + if (useBorderTexel & (I1BIT | J0BIT)) { + depth10 = 1.0; + } + else { + depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1); + } + if (useBorderTexel & (I0BIT | J1BIT)) { + depth01 = 1.0; + } + else { + depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0); + } + if (useBorderTexel & (I1BIT | J1BIT)) { + depth11 = 1.0; + } + else { + depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1); + } + + if (0) { + /* compute a single weighted depth sample and do one comparison */ + const GLfloat a = FRAC(u + 1.0F); + const GLfloat b = FRAC(v + 1.0F); + const GLfloat w00 = (1.0F - a) * (1.0F - b); + const GLfloat w10 = ( a) * (1.0F - b); + const GLfloat w01 = (1.0F - a) * ( b); + const GLfloat w11 = ( a) * ( b); + const GLfloat depthSample = w00 * depth00 + w10 * depth10 + + w01 * depth01 + w11 * depth11; + if ((depthSample <= texcoords[i][2] && lequal) || + (depthSample >= texcoords[i][2] && gequal)) { + result = ambient; } else { - ASSERT(t->MinFilter==GL_NEAREST); - swrast->TextureSample[texUnit] = sample_nearest_1d; + result = CHAN_MAX; } - break; - case 2: - if (needLambda) { - swrast->TextureSample[texUnit] = sample_lambda_2d; + } + else { + /* Do four depth/R comparisons and compute a weighted result. + * If this touches on somebody's I.P., I'll remove this code + * upon request. + */ + const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F; + GLfloat luminance = CHAN_MAXF; + if (lequal) { + if (depth00 <= texcoords[i][2]) luminance -= d; + if (depth01 <= texcoords[i][2]) luminance -= d; + if (depth10 <= texcoords[i][2]) luminance -= d; + if (depth11 <= texcoords[i][2]) luminance -= d; + result = (GLchan) luminance; } - else if (t->MinFilter==GL_LINEAR) { - swrast->TextureSample[texUnit] = sample_linear_2d; + else if (gequal) { + if (depth00 >= texcoords[i][2]) luminance -= d; + if (depth01 >= texcoords[i][2]) luminance -= d; + if (depth10 >= texcoords[i][2]) luminance -= d; + if (depth11 >= texcoords[i][2]) luminance -= d; + result = (GLchan) luminance; } else { - GLint baseLevel = t->BaseLevel; - ASSERT(t->MinFilter==GL_NEAREST); - if (t->WrapS == GL_REPEAT && - t->WrapT == GL_REPEAT && - t->Image[baseLevel]->Border == 0 && - t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGB) { - swrast->TextureSample[texUnit] = opt_sample_rgb_2d; - } - else if (t->WrapS == GL_REPEAT && - t->WrapT == GL_REPEAT && - t->Image[baseLevel]->Border == 0 && - t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGBA) { - swrast->TextureSample[texUnit] = opt_sample_rgba_2d; - } - else - swrast->TextureSample[texUnit] = sample_nearest_2d; + /* no comparison, just bilinear sampling */ + const GLfloat a = FRAC(u + 1.0F); + const GLfloat b = FRAC(v + 1.0F); + const GLfloat w00 = (1.0F - a) * (1.0F - b); + const GLfloat w10 = ( a) * (1.0F - b); + const GLfloat w01 = (1.0F - a) * ( b); + const GLfloat w11 = ( a) * ( b); + const GLfloat depthSample = w00 * depth00 + w10 * depth10 + + w01 * depth01 + w11 * depth11; + CLAMPED_FLOAT_TO_CHAN(result, depthSample); } + } + + switch (tObj->DepthMode) { + case GL_LUMINANCE: + texel[i][RCOMP] = result; + texel[i][GCOMP] = result; + texel[i][BCOMP] = result; + texel[i][ACOMP] = CHAN_MAX; break; - case 3: - if (needLambda) { - swrast->TextureSample[texUnit] = sample_lambda_3d; - } - else if (t->MinFilter==GL_LINEAR) { - swrast->TextureSample[texUnit] = sample_linear_3d; - } - else { - ASSERT(t->MinFilter==GL_NEAREST); - swrast->TextureSample[texUnit] = sample_nearest_3d; - } + case GL_INTENSITY: + texel[i][RCOMP] = result; + texel[i][GCOMP] = result; + texel[i][BCOMP] = result; + texel[i][ACOMP] = result; break; - case 6: /* cube map */ - if (needLambda) { - swrast->TextureSample[texUnit] = sample_lambda_cube; - } - else if (t->MinFilter==GL_LINEAR) { - swrast->TextureSample[texUnit] = sample_linear_cube; - } - else { - ASSERT(t->MinFilter==GL_NEAREST); - swrast->TextureSample[texUnit] = sample_nearest_cube; - } + case GL_ALPHA: + texel[i][RCOMP] = 0; + texel[i][GCOMP] = 0; + texel[i][BCOMP] = 0; + texel[i][ACOMP] = result; break; default: - _mesa_problem(NULL, "invalid dimensions in _mesa_set_texture_sampler"); - } - } + _mesa_problem(ctx, "Bad depth texture mode"); + } + } /* for */ + } /* if filter */ } -#define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) ) -#define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) ) - -static INLINE void -texture_combine(const GLcontext *ctx, - const struct gl_texture_unit *textureUnit, - GLuint n, - CONST GLchan (*primary_rgba)[4], - CONST GLchan (*texel)[4], - GLchan (*rgba)[4]) +#if 0 +/* + * Experimental depth texture sampling function. + */ +static void +sample_depth_texture2(const GLcontext *ctx, + const struct gl_texture_unit *texUnit, + GLuint n, GLfloat texcoords[][4], + GLchan texel[][4]) { - const GLchan (*argRGB [3])[4]; - const GLchan (*argA [3])[4]; - GLuint i, j; - const GLuint RGBshift = textureUnit->CombineScaleShiftRGB; - const GLuint Ashift = textureUnit->CombineScaleShiftA; -#if CHAN_TYPE == GL_FLOAT - const GLchan RGBmult = (GLfloat) (1 << RGBshift); - const GLchan Amult = (GLfloat) (1 << Ashift); -#else - const GLint half = (CHAN_MAX + 1) / 2; -#endif + const struct gl_texture_object *texObj = texUnit->_Current; + const GLint baseLevel = texObj->BaseLevel; + const struct gl_texture_image *texImage = texObj->Image[baseLevel]; + const GLuint width = texImage->Width; + const GLuint height = texImage->Height; + const GLchan ambient = texObj->ShadowAmbient; + GLboolean lequal, gequal; + + if (texObj->Dimensions != 2) { + _mesa_problem(ctx, "only 2-D depth textures supported at this time"); + return; + } + + if (texObj->MinFilter != texObj->MagFilter) { + _mesa_problem(ctx, "mipmapped depth textures not supported at this time"); + return; + } + + /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if + * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object + * isn't a depth texture. + */ + if (texImage->Format != GL_DEPTH_COMPONENT) { + _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture"); + return; + } + + if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { + lequal = GL_TRUE; + gequal = GL_FALSE; + } + else { + lequal = GL_FALSE; + gequal = GL_TRUE; + } + + { + GLuint i; + for (i = 0; i < n; i++) { + const GLint K = 3; + GLint col, row, ii, jj, imin, imax, jmin, jmax, samples, count; + GLfloat w; + GLchan lum; + COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, texcoords[i][0], + width, col); + COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, texcoords[i][1], + height, row); + + imin = col - K; + imax = col + K; + jmin = row - K; + jmax = row + K; + + if (imin < 0) imin = 0; + if (imax >= width) imax = width - 1; + if (jmin < 0) jmin = 0; + if (jmax >= height) jmax = height - 1; + + samples = (imax - imin + 1) * (jmax - jmin + 1); + count = 0; + for (jj = jmin; jj <= jmax; jj++) { + for (ii = imin; ii <= imax; ii++) { + GLfloat depthSample = *((const GLfloat *) texImage->Data + + jj * width + ii); + if ((depthSample <= r[i] && lequal) || + (depthSample >= r[i] && gequal)) { + count++; + } + } + } + + w = (GLfloat) count / (GLfloat) samples; + w = CHAN_MAXF - w * (CHAN_MAXF - (GLfloat) ambient); + lum = (GLint) w; + + texel[i][RCOMP] = lum; + texel[i][GCOMP] = lum; + texel[i][BCOMP] = lum; + texel[i][ACOMP] = CHAN_MAX; + } + } +} +#endif + + +static void +null_sample_func( GLcontext *ctx, GLuint texUnit, + const struct gl_texture_object *tObj, GLuint n, + GLfloat texcoords[][4], const GLfloat lambda[], + GLchan rgba[][4]) +{ +} + + + +/**********************************************************************/ +/* Texture Sampling Setup */ +/**********************************************************************/ + + +/* + * Setup the texture sampling function for this texture object. + */ +void +_swrast_choose_texture_sample_func( GLcontext *ctx, GLuint texUnit, + const struct gl_texture_object *t ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + if (!t->Complete) { + swrast->TextureSample[texUnit] = null_sample_func; + } + else { + const GLboolean needLambda = (GLboolean) (t->MinFilter != t->MagFilter); + const GLenum format = t->Image[t->BaseLevel]->Format; + + if (needLambda) { + /* Compute min/mag filter threshold */ + if (t->MagFilter == GL_LINEAR + && (t->MinFilter == GL_NEAREST_MIPMAP_NEAREST || + t->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) { + swrast->_MinMagThresh[texUnit] = 0.5F; + } + else { + swrast->_MinMagThresh[texUnit] = 0.0F; + } + } + + switch (t->Dimensions) { + case 1: + if (format == GL_DEPTH_COMPONENT) { + swrast->TextureSample[texUnit] = sample_depth_texture; + } + else if (needLambda) { + swrast->TextureSample[texUnit] = sample_lambda_1d; + } + else if (t->MinFilter == GL_LINEAR) { + swrast->TextureSample[texUnit] = sample_linear_1d; + } + else { + ASSERT(t->MinFilter == GL_NEAREST); + swrast->TextureSample[texUnit] = sample_nearest_1d; + } + break; + case 2: + if (format == GL_DEPTH_COMPONENT) { + swrast->TextureSample[texUnit] = sample_depth_texture; + } + else if (needLambda) { + swrast->TextureSample[texUnit] = sample_lambda_2d; + } + else if (t->MinFilter == GL_LINEAR) { + swrast->TextureSample[texUnit] = sample_linear_2d; + } + else { + GLint baseLevel = t->BaseLevel; + ASSERT(t->MinFilter == GL_NEAREST); + if (t->WrapS == GL_REPEAT && + t->WrapT == GL_REPEAT && + t->Image[baseLevel]->Border == 0 && + t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGB) { + swrast->TextureSample[texUnit] = opt_sample_rgb_2d; + } + else if (t->WrapS == GL_REPEAT && + t->WrapT == GL_REPEAT && + t->Image[baseLevel]->Border == 0 && + t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGBA) { + swrast->TextureSample[texUnit] = opt_sample_rgba_2d; + } + else + swrast->TextureSample[texUnit] = sample_nearest_2d; + } + break; + case 3: + if (needLambda) { + swrast->TextureSample[texUnit] = sample_lambda_3d; + } + else if (t->MinFilter == GL_LINEAR) { + swrast->TextureSample[texUnit] = sample_linear_3d; + } + else { + ASSERT(t->MinFilter == GL_NEAREST); + swrast->TextureSample[texUnit] = sample_nearest_3d; + } + break; + case 6: /* cube map */ + if (needLambda) { + swrast->TextureSample[texUnit] = sample_lambda_cube; + } + else if (t->MinFilter == GL_LINEAR) { + swrast->TextureSample[texUnit] = sample_linear_cube; + } + else { + ASSERT(t->MinFilter == GL_NEAREST); + swrast->TextureSample[texUnit] = sample_nearest_cube; + } + break; + default: + _mesa_problem(NULL, "invalid dimensions in _mesa_set_texture_sampler"); + } + } +} + + +#define PROD(A,B) ( (GLuint)(A) * ((GLuint)(B)+1) ) +#define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) ) + +static INLINE void +texture_combine(const GLcontext *ctx, + const struct gl_texture_unit *textureUnit, + GLuint n, + CONST GLchan (*primary_rgba)[4], + CONST GLchan (*texel)[4], + GLchan (*rgba)[4]) +{ + const GLchan (*argRGB [3])[4]; + const GLchan (*argA [3])[4]; + GLuint i, j; + const GLuint RGBshift = textureUnit->CombineScaleShiftRGB; + const GLuint Ashift = textureUnit->CombineScaleShiftA; +#if CHAN_TYPE == GL_FLOAT + const GLchan RGBmult = (GLfloat) (1 << RGBshift); + const GLchan Amult = (GLfloat) (1 << Ashift); +#else + const GLint half = (CHAN_MAX + 1) / 2; +#endif DEFMNARRAY(GLchan, ccolor, 3, 3 * MAX_WIDTH, 4); /* mac 32k limitation */ CHECKARRAY(ccolor, return); /* mac 32k limitation */ @@ -2344,8 +2681,8 @@ apply_texture( const GLcontext *ctx, format = texUnit->_Current->Image[baseLevel]->Format; - if (format==GL_COLOR_INDEX || format==GL_DEPTH_COMPONENT) { - format = GL_RGBA; /* XXXX a hack! */ + if (format == GL_COLOR_INDEX || format == GL_DEPTH_COMPONENT) { + format = GL_RGBA; /* a bit of a hack */ } switch (texUnit->EnvMode) { @@ -2442,550 +2779,229 @@ apply_texture( const GLcontext *ctx, case GL_INTENSITY: for (i=0;iEnvColor[0] * CHAN_MAXF); - Gc = (GLint) (texUnit->EnvColor[1] * CHAN_MAXF); - Bc = (GLint) (texUnit->EnvColor[2] * CHAN_MAXF); - Ac = (GLint) (texUnit->EnvColor[3] * CHAN_MAXF); - switch (format) { - case GL_ALPHA: - for (i=0;i_Current; - const GLint baseLevel = texObj->BaseLevel; - const struct gl_texture_image *texImage = texObj->Image[baseLevel]; - const GLuint width = texImage->Width; - const GLuint height = texImage->Height; - const GLchan ambient = texObj->ShadowAmbient; - GLboolean lequal, gequal; - GLchan result; - - ASSERT(texObj->Image[texObj->BaseLevel]->Format == GL_DEPTH_COMPONENT); - - if (texObj->Dimensions != 2) { - _mesa_problem(ctx, "only 2-D depth textures supported at this time"); - return; - } - - if (texObj->MinFilter != texObj->MagFilter) { - _mesa_problem(ctx, "mipmapped depth textures not supported at this time"); - return; - } - - /* XXX this could be precomputed */ - if (texObj->CompareFlag) { - /* GL_SGIX_shadow */ - if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { - lequal = GL_TRUE; - gequal = GL_FALSE; - } - else { - ASSERT(texObj->CompareOperator == GL_TEXTURE_GEQUAL_R_SGIX); - lequal = GL_FALSE; - gequal = GL_TRUE; - } - } - else if (texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) { - /* GL_ARB_shadow */ - if (texObj->CompareFunc == GL_LEQUAL) { - lequal = GL_TRUE; - gequal = GL_FALSE; - } - else { - ASSERT(texObj->CompareFunc == GL_GEQUAL); - lequal = GL_FALSE; - gequal = GL_TRUE; - } - } - else { - /* Treat this depth texture as a luminance texture */ - _mesa_warning(ctx, - "Treating GL_DEPTH_COMPONENT as GL_LUMINANCE not implemented yet"); - return; - } - - if (texObj->MagFilter == GL_NEAREST) { - GLuint i; - for (i = 0; i < n; i++) { - GLfloat depthSample; - GLint col, row; - COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, texcoords[i][0], width, col); - COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, texcoords[i][1], height, row); - depthSample = *((const GLfloat *) texImage->Data + row * width + col); - if ((texcoords[i][2] <= depthSample && lequal) || - (texcoords[i][2] >= depthSample && gequal)) { - result = CHAN_MAX; - } - else { - result = ambient; - } - - switch (texObj->CompareResult) { - case GL_LUMINANCE: - texel[i][RCOMP] = result; - texel[i][GCOMP] = result; - texel[i][BCOMP] = result; - texel[i][ACOMP] = CHAN_MAX; - break; - case GL_INTENSITY: - texel[i][RCOMP] = result; - texel[i][GCOMP] = result; - texel[i][BCOMP] = result; - texel[i][ACOMP] = result; - break; - case GL_ALPHA: - texel[i][RCOMP] = 0; - texel[i][GCOMP] = 0; - texel[i][BCOMP] = 0; - texel[i][ACOMP] = result; - break; - default: - _mesa_problem(ctx, "Bad texture compare result value"); - } - } - } - else { - GLuint i; - ASSERT(texObj->MagFilter == GL_LINEAR); - for (i = 0; i < n; i++) { - GLfloat depth00, depth01, depth10, depth11; - GLint i0, i1, j0, j1; - GLfloat u, v; - GLuint useBorderTexel; - - COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapS, texcoords[i][0], u, width, i0, i1); - COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapT, texcoords[i][1], v, height,j0, j1); - - useBorderTexel = 0; - if (texImage->Border) { - i0 += texImage->Border; - i1 += texImage->Border; - j0 += texImage->Border; - j1 += texImage->Border; - } - else { - if (i0 < 0 || i0 >= (GLint) width) useBorderTexel |= I0BIT; - if (i1 < 0 || i1 >= (GLint) width) useBorderTexel |= I1BIT; - if (j0 < 0 || j0 >= (GLint) height) useBorderTexel |= J0BIT; - if (j1 < 0 || j1 >= (GLint) height) useBorderTexel |= J1BIT; - } - - /* get four depth samples from the texture */ - if (useBorderTexel & (I0BIT | J0BIT)) { - depth00 = 1.0; - } - else { - depth00 = *((const GLfloat *) texImage->Data + j0 * width + i0); - } - if (useBorderTexel & (I1BIT | J0BIT)) { - depth10 = 1.0; - } - else { - depth10 = *((const GLfloat *) texImage->Data + j0 * width + i1); - } - if (useBorderTexel & (I0BIT | J1BIT)) { - depth01 = 1.0; - } - else { - depth01 = *((const GLfloat *) texImage->Data + j1 * width + i0); - } - if (useBorderTexel & (I1BIT | J1BIT)) { - depth11 = 1.0; - } - else { - depth11 = *((const GLfloat *) texImage->Data + j1 * width + i1); - } - - if (0) { - /* compute a single weighted depth sample and do one comparison */ - const GLfloat a = FRAC(u + 1.0F); - const GLfloat b = FRAC(v + 1.0F); - const GLfloat w00 = (1.0F - a) * (1.0F - b); - const GLfloat w10 = ( a) * (1.0F - b); - const GLfloat w01 = (1.0F - a) * ( b); - const GLfloat w11 = ( a) * ( b); - const GLfloat depthSample = w00 * depth00 + w10 * depth10 - + w01 * depth01 + w11 * depth11; - if ((depthSample <= texcoords[i][2] && lequal) || - (depthSample >= texcoords[i][2] && gequal)) { - result = ambient; - } - else { - result = CHAN_MAX; - } - } - else { - /* Do four depth/R comparisons and compute a weighted result. - * If this touches on somebody's I.P., I'll remove this code - * upon request. - */ - const GLfloat d = (CHAN_MAXF - (GLfloat) ambient) * 0.25F; - GLfloat luminance = CHAN_MAXF; - if (lequal) { - if (depth00 <= texcoords[i][2]) luminance -= d; - if (depth01 <= texcoords[i][2]) luminance -= d; - if (depth10 <= texcoords[i][2]) luminance -= d; - if (depth11 <= texcoords[i][2]) luminance -= d; - } - else { - if (depth00 >= texcoords[i][2]) luminance -= d; - if (depth01 >= texcoords[i][2]) luminance -= d; - if (depth10 >= texcoords[i][2]) luminance -= d; - if (depth11 >= texcoords[i][2]) luminance -= d; - } - result = (GLchan) luminance; - } - - switch (texObj->CompareResult) { - case GL_LUMINANCE: - texel[i][RCOMP] = result; - texel[i][GCOMP] = result; - texel[i][BCOMP] = result; - texel[i][ACOMP] = CHAN_MAX; - break; - case GL_INTENSITY: - texel[i][RCOMP] = result; - texel[i][GCOMP] = result; - texel[i][BCOMP] = result; - texel[i][ACOMP] = result; - break; - case GL_ALPHA: - texel[i][RCOMP] = 0; - texel[i][GCOMP] = 0; - texel[i][BCOMP] = 0; - texel[i][ACOMP] = result; - break; - default: - _mesa_problem(ctx, "Bad texture compare result value"); - } - } /* for */ - } /* if filter */ -} - - -#if 0 -/* - * Experimental depth texture sampling function. - */ -static void -sample_depth_texture2(const GLcontext *ctx, - const struct gl_texture_unit *texUnit, - GLuint n, GLfloat texcoords[][4], - GLchan texel[][4]) -{ - const struct gl_texture_object *texObj = texUnit->_Current; - const GLint baseLevel = texObj->BaseLevel; - const struct gl_texture_image *texImage = texObj->Image[baseLevel]; - const GLuint width = texImage->Width; - const GLuint height = texImage->Height; - const GLchan ambient = texObj->ShadowAmbient; - GLboolean lequal, gequal; - - if (texObj->Dimensions != 2) { - _mesa_problem(ctx, "only 2-D depth textures supported at this time"); - return; - } - - if (texObj->MinFilter != texObj->MagFilter) { - _mesa_problem(ctx, "mipmapped depth textures not supported at this time"); - return; - } - - /* XXX the GL_SGIX_shadow extension spec doesn't say what to do if - * GL_TEXTURE_COMPARE_SGIX == GL_TRUE but the current texture object - * isn't a depth texture. - */ - if (texImage->Format != GL_DEPTH_COMPONENT) { - _mesa_problem(ctx,"GL_TEXTURE_COMPARE_SGIX enabled with non-depth texture"); - return; - } - - if (texObj->CompareOperator == GL_TEXTURE_LEQUAL_R_SGIX) { - lequal = GL_TRUE; - gequal = GL_FALSE; - } - else { - lequal = GL_FALSE; - gequal = GL_TRUE; - } + GLchan It = texel[i][RCOMP]; + rgba[i][RCOMP] = CHAN_PRODUCT( rgba[i][RCOMP], It ); + rgba[i][GCOMP] = CHAN_PRODUCT( rgba[i][GCOMP], It ); + rgba[i][BCOMP] = CHAN_PRODUCT( rgba[i][BCOMP], It ); + /* Av = AfIt */ + rgba[i][ACOMP] = CHAN_PRODUCT( rgba[i][ACOMP], It ); + } + break; + case GL_RGB: + for (i=0;iWrapS, texcoords[i][0], - width, col); - COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, texcoords[i][1], - height, row); + case GL_DECAL: + switch (format) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + /* undefined */ + break; + case GL_RGB: + for (i=0;iEnvColor[0] * CHAN_MAXF); + Gc = (GLint) (texUnit->EnvColor[1] * CHAN_MAXF); + Bc = (GLint) (texUnit->EnvColor[2] * CHAN_MAXF); + Ac = (GLint) (texUnit->EnvColor[3] * CHAN_MAXF); + switch (format) { + case GL_ALPHA: + for (i=0;i= width) imax = width - 1; - if (jmin < 0) jmin = 0; - if (jmax >= height) jmax = height - 1; + /* XXX don't clamp results if GLchan is float??? */ - samples = (imax - imin + 1) * (jmax - jmin + 1); - count = 0; - for (jj = jmin; jj <= jmax; jj++) { - for (ii = imin; ii <= imax; ii++) { - GLfloat depthSample = *((const GLfloat *) texImage->Data - + jj * width + ii); - if ((depthSample <= r[i] && lequal) || - (depthSample >= r[i] && gequal)) { - count++; + case GL_ADD: /* GL_EXT_texture_add_env */ + switch (format) { + case GL_ALPHA: + for (i=0;iImage[curObj->BaseLevel]->Format == GL_DEPTH_COMPONENT) { /* depth texture */ - sample_depth_texture(ctx, textureUnit, n, texcoords, texel); + sample_depth_texture(ctx, texUnit, textureUnit->_Current, + n, texcoords, lambda, texel); } else { /* color texture */ +#endif SWRAST_CONTEXT(ctx)->TextureSample[texUnit]( ctx, texUnit, textureUnit->_Current, n, texcoords, lambda, texel ); +#if 0 } +#endif apply_texture( ctx, textureUnit, n, primary_rgba, (const GLchan (*)[4]) texel, rgba ); }