-/* $Id: s_texture.c,v 1.10 2001/02/07 03:55:31 brianp Exp $ */
+/* $Id: s_texture.c,v 1.14 2001/03/03 20:33:30 brianp Exp $ */
/*
* Mesa 3-D graphics library
/*
* Used to compute texel locations for linear sampling.
+ * Input:
+ * wrapMode = GL_REPEAT, GL_CLAMP or GL_CLAMP_TO_EDGE
+ * S = texcoord in [0,1]
+ * SIZE = width (or height or depth) of texture
+ * Output:
+ * U = texcoord in [0, width]
+ * I0, I1 = two nearest texel indexes
*/
#define COMPUTE_LINEAR_TEXEL_LOCATIONS(wrapMode, S, U, SIZE, I0, I1) \
{ \
+/*
+ * Get texture palette entry.
+ */
+static void
+palette_sample(const GLcontext *ctx,
+ const struct gl_texture_object *tObj,
+ GLint index, GLchan rgba[4] )
+{
+ const GLchan *palette;
+ GLenum format;
+
+ if (ctx->Texture.SharedPalette) {
+ ASSERT(!ctx->Texture.Palette.FloatTable);
+ palette = (const GLchan *) ctx->Texture.Palette.Table;
+ format = ctx->Texture.Palette.Format;
+ }
+ else {
+ ASSERT(!tObj->Palette.FloatTable);
+ palette = (const GLchan *) tObj->Palette.Table;
+ format = tObj->Palette.Format;
+ }
+
+ switch (format) {
+ case GL_ALPHA:
+ rgba[ACOMP] = palette[index];
+ return;
+ case GL_LUMINANCE:
+ case GL_INTENSITY:
+ rgba[RCOMP] = palette[index];
+ return;
+ case GL_LUMINANCE_ALPHA:
+ rgba[RCOMP] = palette[(index << 1) + 0];
+ rgba[ACOMP] = palette[(index << 1) + 1];
+ return;
+ case GL_RGB:
+ rgba[RCOMP] = palette[index * 3 + 0];
+ rgba[GCOMP] = palette[index * 3 + 1];
+ rgba[BCOMP] = palette[index * 3 + 2];
+ return;
+ case GL_RGBA:
+ rgba[RCOMP] = palette[(index << 2) + 0];
+ rgba[GCOMP] = palette[(index << 2) + 1];
+ rgba[BCOMP] = palette[(index << 2) + 2];
+ rgba[ACOMP] = palette[(index << 2) + 3];
+ return;
+ default:
+ _mesa_problem(ctx, "Bad palette format in palette_sample");
+ }
+}
+
+
+
/**********************************************************************/
/* 1-D Texture Sampling Functions */
/**********************************************************************/
/* skip over the border, if any */
i += img->Border;
- (*img->FetchTexel)(ctx, tObj, img, i, 0, 0, rgba);
+ (*img->FetchTexel)(img, i, 0, 0, (GLvoid *) rgba);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, rgba[0], rgba);
+ }
}
COPY_CHAN4(t0, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i0, 0, 0, t0);
+ (*img->FetchTexel)(img, i0, 0, 0, (GLvoid *) t0);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t0[0], t0);
+ }
}
if (useBorderColor & I1BIT) {
COPY_CHAN4(t1, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i1, 0, 0, t1);
+ (*img->FetchTexel)(img, i1, 0, 0, (GLvoid *) t1);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t1[0], t1);
+ }
}
rgba[0] = (GLchan) ((w0 * t0[0] + w1 * t1[0]) >> WEIGHT_SHIFT);
rgba[i]);
break;
default:
- gl_problem(NULL, "Bad min filter in sample_1d_texture");
+ _mesa_problem(NULL, "Bad min filter in sample_1d_texture");
return;
}
}
s[i], rgba[i]);
break;
default:
- gl_problem(NULL, "Bad mag filter in sample_1d_texture");
+ _mesa_problem(NULL, "Bad mag filter in sample_1d_texture");
return;
}
}
i += img->Border;
j += img->Border;
- (*img->FetchTexel)(ctx, tObj, img, i, j, 0, rgba);
+ (*img->FetchTexel)(img, i, j, 0, (GLvoid *) rgba);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, rgba[0], rgba);
+ }
}
COPY_CHAN4(t00, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i0, j0, 0, t00);
+ (*img->FetchTexel)(img, i0, j0, 0, (GLvoid *) t00);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t00[0], t00);
+ }
}
if (useBorderColor & (I1BIT | J0BIT)) {
COPY_CHAN4(t10, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i1, j0, 0, t10);
+ (*img->FetchTexel)(img, i1, j0, 0, (GLvoid *) t10);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t10[0], t10);
+ }
}
if (useBorderColor & (I0BIT | J1BIT)) {
COPY_CHAN4(t01, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i0, j1, 0, t01);
+ (*img->FetchTexel)(img, i0, j1, 0, (GLvoid *) t01);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t01[0], t01);
+ }
}
if (useBorderColor & (I1BIT | J1BIT)) {
COPY_CHAN4(t11, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i1, j1, 0, t11);
+ (*img->FetchTexel)(img, i1, j1, 0, (GLvoid *) t11);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t11[0], t11);
+ }
}
rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT);
s[i], t[i], rgba[i] );
break;
default:
- gl_problem(NULL, "Bad mag filter in sample_2d_texture");
+ _mesa_problem(NULL, "Bad mag filter in sample_2d_texture");
}
}
else {
lambda[i], rgba[i] );
break;
default:
- gl_problem(NULL, "Bad min filter in sample_2d_texture");
+ _mesa_problem(NULL, "Bad min filter in sample_2d_texture");
return;
}
}
s[i], t[i], rgba[i] );
break;
default:
- gl_problem(NULL, "Bad mag filter in sample_2d_texture");
+ _mesa_problem(NULL, "Bad mag filter in sample_2d_texture");
}
}
}
COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapT, t, height, j);
COMPUTE_NEAREST_TEXEL_LOCATION(tObj->WrapR, r, depth, k);
- (*img->FetchTexel)(ctx, tObj, img, i, j, k, rgba);
+ (*img->FetchTexel)(img, i, j, k, (GLvoid *) rgba);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, rgba[0], rgba);
+ }
}
COPY_CHAN4(t000, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i0, j0, k0, t000);
+ (*img->FetchTexel)(img, i0, j0, k0, (GLvoid *) t000);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t000[0], t000);
+ }
}
if (useBorderColor & (I1BIT | J0BIT | K0BIT)) {
COPY_CHAN4(t100, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i1, j0, k0, t100);
+ (*img->FetchTexel)(img, i1, j0, k0, (GLvoid *) t100);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t100[0], t100);
+ }
}
if (useBorderColor & (I0BIT | J1BIT | K0BIT)) {
COPY_CHAN4(t010, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i0, j1, k0, t010);
+ (*img->FetchTexel)(img, i0, j1, k0, (GLvoid *) t010);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t010[0], t010);
+ }
}
if (useBorderColor & (I1BIT | J1BIT | K0BIT)) {
COPY_CHAN4(t110, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i1, j1, k0, t110);
+ (*img->FetchTexel)(img, i1, j1, k0, (GLvoid *) t110);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t110[0], t110);
+ }
}
if (useBorderColor & (I0BIT | J0BIT | K1BIT)) {
COPY_CHAN4(t001, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i0, j0, k1, t001);
+ (*img->FetchTexel)(img, i0, j0, k1, (GLvoid *) t001);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t001[0], t001);
+ }
}
if (useBorderColor & (I1BIT | J0BIT | K1BIT)) {
COPY_CHAN4(t101, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i1, j0, k1, t101);
+ (*img->FetchTexel)(img, i1, j0, k1, (GLvoid *) t101);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t101[0], t101);
+ }
}
if (useBorderColor & (I0BIT | J1BIT | K1BIT)) {
COPY_CHAN4(t011, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i0, j1, k1, t011);
+ (*img->FetchTexel)(img, i0, j1, k1, (GLvoid *) t011);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t011[0], t011);
+ }
}
if (useBorderColor & (I1BIT | J1BIT | K1BIT)) {
COPY_CHAN4(t111, tObj->BorderColor);
}
else {
- (*img->FetchTexel)(ctx, tObj, img, i1, j1, k1, t111);
+ (*img->FetchTexel)(img, i1, j1, k1, (GLvoid *) t111);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, t111[0], t111);
+ }
}
rgba[0] = (GLchan) (
lambda[i], rgba[i]);
break;
default:
- gl_problem(NULL, "Bad min filterin sample_3d_texture");
+ _mesa_problem(NULL, "Bad min filterin sample_3d_texture");
}
}
else {
s[i], t[i], u[i], rgba[i]);
break;
default:
- gl_problem(NULL, "Bad mag filter in sample_3d_texture");
+ _mesa_problem(NULL, "Bad mag filter in sample_3d_texture");
}
}
}
lambda[i], rgba[i]);
break;
default:
- gl_problem(NULL, "Bad min filter in sample_lambda_cube");
+ _mesa_problem(NULL, "Bad min filter in sample_lambda_cube");
}
}
else {
newS, newT, rgba[i]);
break;
default:
- gl_problem(NULL, "Bad mag filter in sample_lambda_cube");
+ _mesa_problem(NULL, "Bad mag filter in sample_lambda_cube");
}
}
}
}
break;
default:
- gl_problem(NULL, "invalid dimensions in _mesa_set_texture_sampler");
+ _mesa_problem(NULL, "invalid dimensions in _mesa_set_texture_sampler");
}
}
}
#define S_PROD(A,B) ( (GLint)(A) * ((GLint)(B)+1) )
static INLINE void
-_mesa_texture_combine(const GLcontext *ctx,
- const struct gl_texture_unit *textureUnit,
- GLuint n,
- GLchan (*primary_rgba)[4],
- GLchan (*texel)[4],
- GLchan (*rgba)[4])
+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])
{
GLchan ccolor [3][3*MAX_WIDTH][4];
- GLchan (*argRGB [3])[4];
- GLchan (*argA [3])[4];
+ const GLchan (*argRGB [3])[4];
+ const GLchan (*argA [3])[4];
GLuint i, j;
const GLuint RGBshift = textureUnit->CombineScaleShiftRGB;
const GLuint Ashift = textureUnit->CombineScaleShiftA;
argA[j] = primary_rgba;
break;
case GL_PREVIOUS_EXT:
- argA[j] = rgba;
+ argA[j] = (const GLchan (*)[4]) rgba;
break;
case GL_CONSTANT_EXT:
{
UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
for (i = 0; i < n; i++)
c[i][ACOMP] = alpha;
- argA[j] = ccolor[j];
+ argA[j] = (const GLchan (*)[4]) ccolor[j];
}
break;
default:
- gl_problem(NULL, "invalid combine source");
+ _mesa_problem(NULL, "invalid combine source");
}
switch (textureUnit->CombineSourceRGB[j]) {
argRGB[j] = primary_rgba;
break;
case GL_PREVIOUS_EXT:
- argRGB[j] = rgba;
+ argRGB[j] = (const GLchan (*)[4]) rgba;
break;
case GL_CONSTANT_EXT:
{
c[i][GCOMP] = green;
c[i][BCOMP] = blue;
}
- argRGB[j] = ccolor[j];
+ argRGB[j] = (const GLchan (*)[4]) ccolor[j];
}
break;
default:
- gl_problem(NULL, "invalid combine source");
+ _mesa_problem(NULL, "invalid combine source");
}
if (textureUnit->CombineOperandRGB[j] != GL_SRC_COLOR) {
- GLchan (*src)[4] = argRGB[j];
+ const GLchan (*src)[4] = argRGB[j];
GLchan (*dst)[4] = ccolor[j];
- argRGB[j] = ccolor[j];
+ argRGB[j] = (const GLchan (*)[4]) ccolor[j];
if (textureUnit->CombineOperandRGB[j] == GL_ONE_MINUS_SRC_COLOR) {
for (i = 0; i < n; i++) {
}
}
else if (textureUnit->CombineOperandRGB[j] == GL_SRC_ALPHA) {
- src = argA[j];
+ src = (const GLchan (*)[4]) argA[j];
for (i = 0; i < n; i++) {
dst[i][RCOMP] = src[i][ACOMP];
dst[i][GCOMP] = src[i][ACOMP];
}
}
else { /* GL_ONE_MINUS_SRC_ALPHA */
- src = argA[j];
+ src = (const GLchan (*)[4]) argA[j];
for (i = 0; i < n; i++) {
dst[i][RCOMP] = CHAN_MAX - src[i][ACOMP];
dst[i][GCOMP] = CHAN_MAX - src[i][ACOMP];
}
if (textureUnit->CombineOperandA[j] == GL_ONE_MINUS_SRC_ALPHA) {
- GLchan (*src)[4] = argA[j];
+ const GLchan (*src)[4] = argA[j];
GLchan (*dst)[4] = ccolor[j];
- argA[j] = ccolor[j];
+ argA[j] = (const GLchan (*)[4]) ccolor[j];
for (i = 0; i < n; i++) {
dst[i][ACOMP] = CHAN_MAX - src[i][ACOMP];
}
}
break;
default:
- gl_problem(NULL, "invalid combine mode");
+ _mesa_problem(NULL, "invalid combine mode");
}
switch (textureUnit->CombineModeA) {
}
break;
default:
- gl_problem(NULL, "invalid combine mode");
+ _mesa_problem(NULL, "invalid combine mode");
}
/* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
* Input: textureUnit - pointer to texture unit to apply
* format - base internal texture format
* n - number of fragments
- * primary_rgba - primary colors (may be rgba for single texture)
+ * primary_rgba - primary colors (may alias rgba for single texture)
* texels - array of texel colors
* InOut: rgba - incoming fragment colors modified by texel colors
* according to the texture environment mode.
apply_texture( const GLcontext *ctx,
const struct gl_texture_unit *texUnit,
GLuint n,
- GLchan primary_rgba[][4], GLchan texel[][4],
+ CONST GLchan primary_rgba[][4], CONST GLchan texel[][4],
GLchan rgba[][4] )
{
GLint baseLevel;
format = texUnit->_Current->Image[baseLevel]->Format;
- if (format==GL_COLOR_INDEX) {
+ if (format==GL_COLOR_INDEX || format==GL_DEPTH_COMPONENT) {
format = GL_RGBA; /* XXXX a hack! */
}
}
break;
default:
- gl_problem(ctx, "Bad format (GL_REPLACE) in apply_texture");
+ _mesa_problem(ctx, "Bad format (GL_REPLACE) in apply_texture");
return;
}
break;
}
break;
default:
- gl_problem(ctx, "Bad format (GL_MODULATE) in apply_texture");
+ _mesa_problem(ctx, "Bad format (GL_MODULATE) in apply_texture");
return;
}
break;
}
break;
default:
- gl_problem(ctx, "Bad format (GL_DECAL) in apply_texture");
+ _mesa_problem(ctx, "Bad format (GL_DECAL) in apply_texture");
return;
}
break;
}
break;
default:
- gl_problem(ctx, "Bad format (GL_BLEND) in apply_texture");
+ _mesa_problem(ctx, "Bad format (GL_BLEND) in apply_texture");
return;
}
break;
}
break;
default:
- gl_problem(ctx, "Bad format (GL_ADD) in apply_texture");
+ _mesa_problem(ctx, "Bad format (GL_ADD) in apply_texture");
return;
}
break;
- case GL_COMBINE_EXT: /* GL_EXT_combine_ext; we modify texel array */
- switch (format) {
- case GL_ALPHA:
- for (i=0;i<n;i++)
- texel[i][RCOMP] = texel[i][GCOMP] = texel[i][BCOMP] = 0;
- break;
- case GL_LUMINANCE:
- for (i=0;i<n;i++) {
- /* Cv = Lt */
- GLchan Lt = texel[i][RCOMP];
- texel[i][GCOMP] = texel[i][BCOMP] = Lt;
- /* Av = 1 */
- texel[i][ACOMP] = CHAN_MAX;
- }
- break;
- case GL_LUMINANCE_ALPHA:
- for (i=0;i<n;i++) {
- GLchan Lt = texel[i][RCOMP];
- /* Cv = Lt */
- texel[i][GCOMP] = texel[i][BCOMP] = Lt;
- }
- break;
- case GL_INTENSITY:
- for (i=0;i<n;i++) {
- /* Cv = It */
- GLchan It = texel[i][RCOMP];
- texel[i][GCOMP] = texel[i][BCOMP] = It;
- /* Av = It */
- texel[i][ACOMP] = It;
- }
- break;
- case GL_RGB:
- for (i=0;i<n;i++) {
- /* Av = 1 */
- texel[i][ACOMP] = CHAN_MAX;
- }
- break;
- case GL_RGBA: /* do nothing. */
- break;
- default:
- gl_problem(ctx, "Bad format in apply_texture (GL_COMBINE_EXT)");
- return;
- }
- _mesa_texture_combine(ctx, texUnit, n, primary_rgba, texel, rgba);
+ case GL_COMBINE_EXT:
+ texture_combine(ctx, texUnit, n, primary_rgba, texel, rgba);
break;
default:
- gl_problem(ctx, "Bad env mode in apply_texture");
+ _mesa_problem(ctx, "Bad env mode in apply_texture");
return;
}
}
+/*
+ * Sample a shadow/depth texture.
+ * Input: ctx - context
+ * texUnit - the texture unit
+ * n - number of samples
+ * s,t,r - array [n] of texture coordinates
+ * In/Out: rgba - array [n] of texel colors.
+ */
+static void
+sample_depth_texture(const GLcontext *ctx,
+ const struct gl_texture_unit *texUnit,
+ GLuint n,
+ const GLfloat s[], const GLfloat t[], const GLfloat r[],
+ 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;
+ }
+
+ if (texObj->MagFilter == GL_NEAREST) {
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ GLfloat depthSample;
+ GLint col, row;
+ COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapS, s[i], width, col);
+ COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], height, row);
+ depthSample = *((const GLfloat *) texImage->Data + row * width + col);
+ if ((depthSample <= r[i] && lequal) ||
+ (depthSample >= r[i] && gequal)) {
+ texel[i][RCOMP] = ambient;
+ texel[i][GCOMP] = ambient;
+ texel[i][BCOMP] = ambient;
+ texel[i][ACOMP] = CHAN_MAX;
+ }
+ else {
+ texel[i][RCOMP] = CHAN_MAX;
+ texel[i][GCOMP] = CHAN_MAX;
+ texel[i][BCOMP] = CHAN_MAX;
+ texel[i][ACOMP] = CHAN_MAX;
+ }
+ }
+ }
+ 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, s[i], u, width, i0, i1);
+ COMPUTE_LINEAR_TEXEL_LOCATIONS(texObj->WrapT, t[i], 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 >= width) useBorderTexel |= I0BIT;
+ if (i1 < 0 || i1 >= width) useBorderTexel |= I1BIT;
+ if (j0 < 0 || j0 >= height) useBorderTexel |= J0BIT;
+ if (j1 < 0 || j1 >= 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);
+ const GLfloat b = FRAC(v);
+ 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 <= r[i] && lequal) ||
+ (depthSample >= r[i] && gequal)) {
+ texel[i][RCOMP] = ambient;
+ texel[i][GCOMP] = ambient;
+ texel[i][BCOMP] = ambient;
+ texel[i][ACOMP] = CHAN_MAX;
+ }
+ else {
+ texel[i][RCOMP] = CHAN_MAX;
+ texel[i][GCOMP] = CHAN_MAX;
+ texel[i][BCOMP] = CHAN_MAX;
+ texel[i][ACOMP] = 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;
+ GLchan lum;
+ if (lequal) {
+ if (depth00 <= r[i]) luminance -= d;
+ if (depth01 <= r[i]) luminance -= d;
+ if (depth10 <= r[i]) luminance -= d;
+ if (depth11 <= r[i]) luminance -= d;
+ }
+ else {
+ if (depth00 >= r[i]) luminance -= d;
+ if (depth01 >= r[i]) luminance -= d;
+ if (depth10 >= r[i]) luminance -= d;
+ if (depth11 >= r[i]) luminance -= d;
+ }
+ lum = (GLchan) luminance;
+ texel[i][RCOMP] = lum;
+ texel[i][GCOMP] = lum;
+ texel[i][BCOMP] = lum;
+ texel[i][ACOMP] = CHAN_MAX;
+ }
+ }
+ }
+}
+
+
+#if 0
+/*
+ * Experimental depth texture sampling function.
+ */
+static void
+sample_depth_texture2(const GLcontext *ctx,
+ const struct gl_texture_unit *texUnit,
+ GLuint n,
+ const GLfloat s[], const GLfloat t[], const GLfloat r[],
+ 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;
+ }
+
+ {
+ 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, s[i], width, col);
+ COMPUTE_NEAREST_TEXEL_LOCATION(texObj->WrapT, t[i], 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
+
+
/*
* Apply a unit of texture mapping to the incoming fragments.
*/
_swrast_texture_fragments( GLcontext *ctx, GLuint texUnit, GLuint n,
const GLfloat s[], const GLfloat t[],
const GLfloat r[], GLfloat lambda[],
- GLchan primary_rgba[][4], GLchan rgba[][4] )
+ CONST GLchan primary_rgba[][4], GLchan rgba[][4] )
{
const GLuint mask = TEXTURE0_ANY << (texUnit * 4);
if (textureUnit->_Current->MinLod != -1000.0
|| textureUnit->_Current->MaxLod != 1000.0) {
/* apply LOD clamping to lambda */
- GLfloat min = textureUnit->_Current->MinLod;
- GLfloat max = textureUnit->_Current->MaxLod;
+ const GLfloat min = textureUnit->_Current->MinLod;
+ const GLfloat max = textureUnit->_Current->MaxLod;
GLuint i;
for (i=0;i<n;i++) {
GLfloat l = lambda[i];
}
/* Sample the texture. */
- SWRAST_CONTEXT(ctx)->TextureSample[texUnit]( ctx, texUnit,
- textureUnit->_Current,
- n, s, t, r,
- lambda, texel );
-
- apply_texture( ctx, textureUnit, n, primary_rgba, texel, rgba );
+ if (textureUnit->_Current->CompareFlag) {
+ /* depth texture */
+ sample_depth_texture(ctx, textureUnit, n, s, t, r, texel);
+ }
+ else {
+ /* color texture */
+ SWRAST_CONTEXT(ctx)->TextureSample[texUnit]( ctx, texUnit,
+ textureUnit->_Current,
+ n, s, t, r,
+ lambda, texel );
+ }
+ apply_texture( ctx, textureUnit, n, primary_rgba,
+ (const GLchan (*)[4]) texel, rgba );
}
}
}