-/* $Id: s_texture.c,v 1.10 2001/02/07 03:55:31 brianp Exp $ */
+/* $Id: s_texture.c,v 1.32 2001/06/01 13:23:27 brianp Exp $ */
/*
* Mesa 3-D graphics library
#include "macros.h"
#include "mmath.h"
#include "mem.h"
+#include "texformat.h"
#include "teximage.h"
#include "s_context.h"
#include "s_texture.h"
-
/*
* These values are used in the fixed-point arithmetic used
* for linear filtering.
/*
* Used to compute texel locations for linear sampling.
+ * Input:
+ * wrapMode = GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER_ARB
+ * 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) \
{ \
I0 = IFLOOR(U) & (SIZE - 1); \
I1 = (I0 + 1) & (SIZE - 1); \
} \
+ else if (wrapMode == GL_CLAMP_TO_EDGE) { \
+ if (S <= 0.0F) \
+ U = 0.0F; \
+ else if (S >= 1.0F) \
+ U = SIZE; \
+ else \
+ U = S * SIZE; \
+ U -= 0.5F; \
+ I0 = IFLOOR(U); \
+ I1 = I0 + 1; \
+ if (I0 < 0) \
+ I0 = 0; \
+ if (I1 >= (GLint) SIZE) \
+ I1 = SIZE - 1; \
+ } \
+ else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
+ const GLfloat min = -1.0F / (2.0F * SIZE); \
+ const GLfloat max = 1.0F - min; \
+ if (S <= min) \
+ U = min * SIZE; \
+ else if (S >= max) \
+ U = max * SIZE; \
+ else \
+ U = S * SIZE; \
+ U -= 0.5F; \
+ I0 = IFLOOR(U); \
+ I1 = I0 + 1; \
+ } \
else { \
- U = S * SIZE; \
- if (U < 0.0F) \
+ ASSERT(wrapMode == GL_CLAMP); \
+ if (S <= 0.0F) \
U = 0.0F; \
- else if (U >= SIZE) \
+ else if (S >= 1.0F) \
U = SIZE; \
+ else \
+ U = S * SIZE; \
U -= 0.5F; \
I0 = IFLOOR(U); \
I1 = I0 + 1; \
- if (wrapMode == GL_CLAMP_TO_EDGE) { \
- if (I0 < 0) \
- I0 = 0; \
- if (I1 >= SIZE) \
- I1 = SIZE - 1; \
- } \
} \
}
{ \
if (wrapMode == GL_REPEAT) { \
/* s limited to [0,1) */ \
- /* i limited to [0,width-1] */ \
- I = (GLint) (S * SIZE); \
- if (S < 0.0F) \
- I -= 1; \
+ /* i limited to [0,size-1] */ \
+ I = IFLOOR(S * SIZE); \
I &= (SIZE - 1); \
} \
else if (wrapMode == GL_CLAMP_TO_EDGE) { \
+ /* s limited to [min,max] */ \
+ /* i limited to [0, size-1] */ \
const GLfloat min = 1.0F / (2.0F * SIZE); \
const GLfloat max = 1.0F - min; \
if (S < min) \
else if (S > max) \
I = SIZE - 1; \
else \
- I = (GLint) (S * SIZE); \
+ I = IFLOOR(S * SIZE); \
+ } \
+ else if (wrapMode == GL_CLAMP_TO_BORDER_ARB) { \
+ /* s limited to [min,max] */ \
+ /* i limited to [-1, size] */ \
+ const GLfloat min = -1.0F / (2.0F * SIZE); \
+ const GLfloat max = 1.0F - min; \
+ if (S <= min) \
+ I = -1; \
+ else if (S >= max) \
+ I = SIZE; \
+ else \
+ I = IFLOOR(S * SIZE); \
} \
else { \
ASSERT(wrapMode == GL_CLAMP); \
/* s limited to [0,1] */ \
- /* i limited to [0,width-1] */ \
+ /* i limited to [0,size-1] */ \
if (S <= 0.0F) \
I = 0; \
else if (S >= 1.0F) \
I = SIZE - 1; \
else \
- I = (GLint) (S * SIZE); \
+ I = IFLOOR(S * SIZE); \
} \
}
+/*
+ * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes
+ * see 1-pixel bands of improperly weighted linear-sampled texels. The
+ * tests/texwrap.c demo is a good test.
+ * Also note, FRAC(x) doesn't truly return the fractional part of x for x < 0.
+ * Instead, if x < 0 then FRAC(x) = 1 - true_frac(x).
+ */
+#define FRAC(f) ((f) - IFLOOR(f))
+
+
/*
* Bitflags for texture border color sampling.
+/*
+ * 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);
+ if (i < 0 || i >= (GLint) img->Width) {
+ /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
+ COPY_CHAN4(rgba, tObj->BorderColor);
+ }
+ else {
+ (*img->FetchTexel)(img, i, 0, 0, (GLvoid *) rgba);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, rgba[0], rgba);
+ }
+ }
}
{
const GLfloat a = FRAC(u);
+
+#if CHAN_BITS == 32
+ const GLfloat w0 = (1.0F-a);
+ const GLfloat w1 = a ;
+#else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
/* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
- const GLint w0 = (GLint) ((1.0F-a) * WEIGHT_SCALE + 0.5F);
- const GLint w1 = (GLint) ( a * WEIGHT_SCALE + 0.5F);
+ const GLint w0 = IROUND_POS((1.0F - a) * WEIGHT_SCALE);
+ const GLint w1 = IROUND_POS( a * WEIGHT_SCALE);
+#endif
GLchan t0[4], t1[4]; /* texels */
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);
+ }
}
+#if CHAN_BITS == 32
+ rgba[0] = w0 * t0[0] + w1 * t1[0];
+ rgba[1] = w0 * t0[1] + w1 * t1[1];
+ rgba[2] = w0 * t0[2] + w1 * t1[2];
+ rgba[3] = w0 * t0[3] + w1 * t1[3];
+#else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
rgba[0] = (GLchan) ((w0 * t0[0] + w1 * t1[0]) >> WEIGHT_SHIFT);
rgba[1] = (GLchan) ((w0 * t0[1] + w1 * t1[1]) >> WEIGHT_SHIFT);
rgba[2] = (GLchan) ((w0 * t0[2] + w1 * t1[2]) >> WEIGHT_SHIFT);
rgba[3] = (GLchan) ((w0 * t0[3] + w1 * t1[3]) >> WEIGHT_SHIFT);
+#endif
+
}
}
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);
+ if (i < 0 || i >= (GLint) img->Width || j < 0 || j >= (GLint) img->Height) {
+ /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
+ COPY_CHAN4(rgba, tObj->BorderColor);
+ }
+ else {
+ (*img->FetchTexel)(img, i, j, 0, (GLvoid *) rgba);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, rgba[0], rgba);
+ }
+ }
}
{
const GLfloat a = FRAC(u);
const GLfloat b = FRAC(v);
+
+#if CHAN_BITS == 32
+ 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 ;
+#else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
/* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
- const GLint w00 = (GLint) ((1.0F-a)*(1.0F-b) * WEIGHT_SCALE + 0.5F);
- const GLint w10 = (GLint) ( a *(1.0F-b) * WEIGHT_SCALE + 0.5F);
- const GLint w01 = (GLint) ((1.0F-a)* b * WEIGHT_SCALE + 0.5F);
- const GLint w11 = (GLint) ( a * b * WEIGHT_SCALE + 0.5F);
+ const GLint w00 = IROUND_POS((1.0F-a) * (1.0F-b) * WEIGHT_SCALE);
+ const GLint w10 = IROUND_POS( a * (1.0F-b) * WEIGHT_SCALE);
+ const GLint w01 = IROUND_POS((1.0F-a) * b * WEIGHT_SCALE);
+ const GLint w11 = IROUND_POS( a * b * WEIGHT_SCALE);
+#endif
+
GLchan t00[4];
GLchan t10[4];
GLchan t01[4];
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);
+ }
}
-
+#if CHAN_BITS == 32
+ rgba[0] = w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0];
+ rgba[1] = w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1];
+ rgba[2] = w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2];
+ rgba[3] = w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3];
+#else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
rgba[0] = (GLchan) ((w00 * t00[0] + w10 * t10[0] + w01 * t01[0] + w11 * t11[0]) >> WEIGHT_SHIFT);
rgba[1] = (GLchan) ((w00 * t00[1] + w10 * t10[1] + w01 * t01[1] + w11 * t11[1]) >> WEIGHT_SHIFT);
rgba[2] = (GLchan) ((w00 * t00[2] + w10 * t10[2] + w01 * t01[2] + w11 * t11[2]) >> WEIGHT_SHIFT);
rgba[3] = (GLchan) ((w00 * t00[3] + w10 * t10[3] + w01 * t01[3] + w11 * t11[3]) >> WEIGHT_SHIFT);
+#endif
+
}
}
GLuint i;
(void) u;
- /* check if lambda is monotonous-array */
+ /* since lambda is monotonous-array use this check first */
if (lambda[0] <= minMagThresh && lambda[n-1] <= minMagThresh) {
- /* magnification */
+ /* magnification for whole span */
switch (tObj->MagFilter) {
case GL_NEAREST:
- for (i = 0; i < n; i++)
- sample_2d_nearest(ctx, tObj, tObj->Image[tObj->BaseLevel],
- s[i], t[i], rgba[i] );
+ sample_nearest_2d(ctx, texUnit, tObj, n, s, t, u,
+ lambda, rgba);
break;
case GL_LINEAR:
- for (i = 0; i < n; i++)
- sample_2d_linear(ctx, tObj, tObj->Image[tObj->BaseLevel],
- s[i], t[i], rgba[i] );
+ sample_linear_2d(ctx, texUnit, tObj, n, s, t, u,
+ lambda, rgba);
break;
default:
- gl_problem(NULL, "Bad mag filter in sample_2d_texture");
+ _mesa_problem(NULL, "Bad mag filter in sample_lambda_2d");
}
}
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);
+ if (i < 0 || i >= (GLint) img->Width ||
+ j < 0 || j >= (GLint) img->Height ||
+ k < 0 || k >= (GLint) img->Depth) {
+ /* Need this test for GL_CLAMP_TO_BORDER_ARB mode */
+ COPY_CHAN4(rgba, tObj->BorderColor);
+ }
+ else {
+ (*img->FetchTexel)(img, i, j, k, (GLvoid *) rgba);
+ if (img->Format == GL_COLOR_INDEX) {
+ palette_sample(ctx, tObj, rgba[0], rgba);
+ }
+ }
}
const GLfloat a = FRAC(u);
const GLfloat b = FRAC(v);
const GLfloat c = FRAC(w);
+
+#if CHAN_BITS == 32
+ /* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
+ GLfloat w000 = (1.0F-a) * (1.0F-b) * (1.0F-c);
+ GLfloat w100 = a * (1.0F-b) * (1.0F-c);
+ GLfloat w010 = (1.0F-a) * b * (1.0F-c);
+ GLfloat w110 = a * b * (1.0F-c);
+ GLfloat w001 = (1.0F-a) * (1.0F-b) * c ;
+ GLfloat w101 = a * (1.0F-b) * c ;
+ GLfloat w011 = (1.0F-a) * b * c ;
+ GLfloat w111 = a * b * c ;
+#else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
/* compute sample weights in fixed point in [0,WEIGHT_SCALE] */
- GLint w000 = (GLint) ((1.0F-a)*(1.0F-b)*(1.0F-c) * WEIGHT_SCALE + 0.5F);
- GLint w100 = (GLint) ( a *(1.0F-b)*(1.0F-c) * WEIGHT_SCALE + 0.5F);
- GLint w010 = (GLint) ((1.0F-a)* b *(1.0F-c) * WEIGHT_SCALE + 0.5F);
- GLint w110 = (GLint) ( a * b *(1.0F-c) * WEIGHT_SCALE + 0.5F);
- GLint w001 = (GLint) ((1.0F-a)*(1.0F-b)* c * WEIGHT_SCALE + 0.5F);
- GLint w101 = (GLint) ( a *(1.0F-b)* c * WEIGHT_SCALE + 0.5F);
- GLint w011 = (GLint) ((1.0F-a)* b * c * WEIGHT_SCALE + 0.5F);
- GLint w111 = (GLint) ( a * b * c * WEIGHT_SCALE + 0.5F);
+ GLint w000 = IROUND_POS((1.0F-a) * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
+ GLint w100 = IROUND_POS( a * (1.0F-b) * (1.0F-c) * WEIGHT_SCALE);
+ GLint w010 = IROUND_POS((1.0F-a) * b * (1.0F-c) * WEIGHT_SCALE);
+ GLint w110 = IROUND_POS( a * b * (1.0F-c) * WEIGHT_SCALE);
+ GLint w001 = IROUND_POS((1.0F-a) * (1.0F-b) * c * WEIGHT_SCALE);
+ GLint w101 = IROUND_POS( a * (1.0F-b) * c * WEIGHT_SCALE);
+ GLint w011 = IROUND_POS((1.0F-a) * b * c * WEIGHT_SCALE);
+ GLint w111 = IROUND_POS( a * b * c * WEIGHT_SCALE);
+#endif
GLchan t000[4], t010[4], t001[4], t011[4];
GLchan t100[4], t110[4], t101[4], t111[4];
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);
+ }
}
+#if CHAN_BITS == 32
+ rgba[0] = w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
+ w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0];
+ rgba[1] = w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
+ w100*t100[1] + w110*t110[1] + w101*t101[1] + w111*t111[1];
+ rgba[2] = w000*t000[2] + w010*t010[2] + w001*t001[2] + w011*t011[2] +
+ w100*t100[2] + w110*t110[2] + w101*t101[2] + w111*t111[2];
+ rgba[3] = w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
+ w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3];
+#else /* CHAN_BITS == 8 || CHAN_BITS == 16 */
rgba[0] = (GLchan) (
(w000*t000[0] + w010*t010[0] + w001*t001[0] + w011*t011[0] +
- w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0] )
+ w100*t100[0] + w110*t110[0] + w101*t101[0] + w111*t111[0] )
>> WEIGHT_SHIFT);
rgba[1] = (GLchan) (
(w000*t000[1] + w010*t010[1] + w001*t001[1] + w011*t011[1] +
(w000*t000[3] + w010*t010[3] + w001*t001[3] + w011*t011[3] +
w100*t100[3] + w110*t110[3] + w101*t101[3] + w111*t111[3] )
>> WEIGHT_SHIFT);
+#endif
+
}
}
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");
}
}
}
if (t->WrapS == GL_REPEAT &&
t->WrapT == GL_REPEAT &&
t->Image[baseLevel]->Border == 0 &&
- t->Image[baseLevel]->Format == GL_RGB &&
- t->Image[baseLevel]->Type == CHAN_TYPE) {
+ 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]->Format==GL_RGBA &&
- t->Image[baseLevel]->Type == CHAN_TYPE) {
+ t->Image[baseLevel]->TexFormat->MesaFormat == MESA_FORMAT_RGBA) {
swrast->TextureSample[texUnit] = opt_sample_rgba_2d;
}
else
}
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;
+ DEFMNARRAY(GLchan, ccolor, 3, 3 * MAX_WIDTH, 4); /* mac 32k limitation */
+ CHECKARRAY(ccolor, return); /* mac 32k limitation */
- ASSERT(ctx->Extensions.EXT_texture_env_combine);
+ ASSERT(ctx->Extensions.EXT_texture_env_combine ||
+ ctx->Extensions.ARB_texture_env_combine);
+ /*
+ * Do operand setup for up to 3 operands. Loop over the terms.
+ */
for (j = 0; j < 3; j++) {
switch (textureUnit->CombineSourceA[j]) {
case GL_TEXTURE:
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:
{
GLchan (*c)[4] = ccolor[j];
- GLchan red, green, blue;
+ GLchan red, green, blue, alpha;
UNCLAMPED_FLOAT_TO_CHAN(red, textureUnit->EnvColor[0]);
UNCLAMPED_FLOAT_TO_CHAN(green, textureUnit->EnvColor[1]);
UNCLAMPED_FLOAT_TO_CHAN(blue, textureUnit->EnvColor[2]);
+ UNCLAMPED_FLOAT_TO_CHAN(alpha, textureUnit->EnvColor[3]);
for (i = 0; i < n; i++) {
c[i][RCOMP] = red;
c[i][GCOMP] = green;
c[i][BCOMP] = blue;
+ c[i][ACOMP] = alpha;
}
- 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];
+ /* point to new arg[j] storage */
+ 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];
for (i = 0; i < n; i++) {
dst[i][RCOMP] = src[i][ACOMP];
dst[i][GCOMP] = src[i][ACOMP];
dst[i][BCOMP] = src[i][ACOMP];
}
}
- else { /* GL_ONE_MINUS_SRC_ALPHA */
- src = argA[j];
+ else {
+ ASSERT(textureUnit->CombineOperandRGB[j] ==GL_ONE_MINUS_SRC_ALPHA);
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];
}
}
}
+ /*
+ * Do the texture combine.
+ */
switch (textureUnit->CombineModeRGB) {
case GL_REPLACE:
{
}
}
break;
+ case GL_SUBTRACT_ARB:
+ {
+ const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
+ const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
+ for (i = 0; i < n; i++) {
+ GLint r = ((GLint) arg0[i][RCOMP] - (GLint) arg1[i][RCOMP]) << RGBshift;
+ GLint g = ((GLint) arg0[i][GCOMP] - (GLint) arg1[i][GCOMP]) << RGBshift;
+ GLint b = ((GLint) arg0[i][BCOMP] - (GLint) arg1[i][BCOMP]) << RGBshift;
+ rgba[i][RCOMP] = (GLchan) CLAMP(r, 0, CHAN_MAX);
+ rgba[i][GCOMP] = (GLchan) CLAMP(g, 0, CHAN_MAX);
+ rgba[i][BCOMP] = (GLchan) CLAMP(b, 0, CHAN_MAX);
+ }
+ }
+ break;
case GL_DOT3_RGB_EXT:
case GL_DOT3_RGBA_EXT:
+ case GL_DOT3_RGB_ARB:
+ case GL_DOT3_RGBA_ARB:
{
- const GLubyte (*arg0)[4] = (const GLubyte (*)[4]) argRGB[0];
- const GLubyte (*arg1)[4] = (const GLubyte (*)[4]) argRGB[1];
+ const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
+ const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
/* ATI's EXT extension has a constant scale by 4. The ARB
* one will likely remove this restriction, and we should
* drop the EXT extension in favour of the ARB one.
(GLint)arg1[i][GCOMP] - 128) +
S_PROD((GLint)arg0[i][BCOMP] - 128,
(GLint)arg1[i][BCOMP] - 128)) >> 6;
- rgba[i][RCOMP] = (GLubyte) CLAMP(dot, 0, 255);
- rgba[i][GCOMP] = (GLubyte) CLAMP(dot, 0, 255);
- rgba[i][BCOMP] = (GLubyte) CLAMP(dot, 0, 255);
+ dot = CLAMP(dot, 0, 255);
+ rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = (GLchan) dot;
}
}
break;
default:
- gl_problem(NULL, "invalid combine mode");
+ _mesa_problem(NULL, "invalid combine mode");
}
switch (textureUnit->CombineModeA) {
}
}
break;
+ case GL_SUBTRACT_ARB:
+ {
+ const GLchan (*arg0)[4] = (const GLchan (*)[4]) argRGB[0];
+ const GLchan (*arg1)[4] = (const GLchan (*)[4]) argRGB[1];
+ for (i = 0; i < n; i++) {
+ GLint a = ((GLint) arg0[i][ACOMP] - (GLint) arg1[i][ACOMP]) << RGBshift;
+ rgba[i][ACOMP] = (GLchan) CLAMP(a, 0, CHAN_MAX);
+ }
+ }
+ break;
+
default:
- gl_problem(NULL, "invalid combine mode");
+ _mesa_problem(NULL, "invalid combine mode");
}
/* Fix the alpha component for GL_DOT3_RGBA_EXT combining.
*/
- if (textureUnit->CombineModeRGB == GL_DOT3_RGBA_EXT) {
+ if (textureUnit->CombineModeRGB == GL_DOT3_RGBA_EXT ||
+ textureUnit->CombineModeRGB == GL_DOT3_RGBA_ARB) {
for (i = 0; i < n; i++) {
rgba[i][ACOMP] = rgba[i][RCOMP];
}
}
+ UNDEFARRAY(ccolor); /* mac 32k limitation */
}
#undef PROD
* 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 ((r[i] <= depthSample && lequal) ||
+ (r[i] >= depthSample && gequal)) {
+ texel[i][RCOMP] = CHAN_MAX;
+ texel[i][GCOMP] = CHAN_MAX;
+ texel[i][BCOMP] = CHAN_MAX;
+ texel[i][ACOMP] = CHAN_MAX;
+ }
+ else {
+ texel[i][RCOMP] = ambient;
+ texel[i][GCOMP] = ambient;
+ texel[i][BCOMP] = ambient;
+ 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 >= (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 <= 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) {
+ if ((textureUnit->_Current->MinLod != -1000.0
+ || textureUnit->_Current->MaxLod != 1000.0)
+ && lambda) {
/* 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 );
}
}
}