X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fsoftpipe%2Fsp_tex_sample.c;h=1ae8fecacf7706c46bf80d732d0c440d7a887f1a;hb=080c40ab32b2abd6d8381b4a0cc143d36a1652b2;hp=21031c11b88bb80fa91fb48aaeb0732ea3877075;hpb=890679d4322e7ba4f12f32532a3fdd277edff886;p=mesa.git diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index 21031c11b88..1ae8fecacf7 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -2,7 +2,7 @@ * * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. - * Copyright 2008 VMware, Inc. All rights reserved. + * Copyright 2008-2010 VMware, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -46,13 +46,18 @@ /* - * Note, the FRAC macro has to work perfectly. Otherwise you'll sometimes - * see 1-pixel bands of improperly weighted linear-filtered textures. + * Return fractional part of 'f'. Used for computing interpolation weights. + * Need to be careful with negative values. + * Note, if this function isn't perfect you'll sometimes see 1-pixel bands + * of improperly weighted linear-filtered textures. * 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) - util_ifloor(f)) +static INLINE float +frac(float f) +{ + return f - util_ifloor(f); +} + /** @@ -99,10 +104,16 @@ lerp_3d(float a, float b, float c, /** - * If A is a signed integer, A % B doesn't give the right value for A < 0 - * (in terms of texture repeat). Just casting to unsigned fixes that. + * Compute coord % size for repeat wrap modes. + * Note that if coord is a signed integer, coord % size doesn't give + * the right value for coord < 0 (in terms of texture repeat). Just + * casting to unsigned fixes that. */ -#define REMAINDER(A, B) ((unsigned) (A) % (unsigned) (B)) +static INLINE int +repeat(int coord, unsigned size) +{ + return (int) ((unsigned) coord % size); +} /** @@ -115,23 +126,20 @@ lerp_3d(float a, float b, float c, * \return integer texture index */ static void -wrap_nearest_repeat(const float s[4], unsigned size, - int icoord[4]) +wrap_nearest_repeat(const float s[4], unsigned size, int icoord[4]) { uint ch; - /* s limited to [0,1) */ /* i limited to [0,size-1] */ for (ch = 0; ch < 4; ch++) { int i = util_ifloor(s[ch] * size); - icoord[ch] = REMAINDER(i, size); + icoord[ch] = repeat(i, size); } } static void -wrap_nearest_clamp(const float s[4], unsigned size, - int icoord[4]) +wrap_nearest_clamp(const float s[4], unsigned size, int icoord[4]) { uint ch; /* s limited to [0,1] */ @@ -148,8 +156,7 @@ wrap_nearest_clamp(const float s[4], unsigned size, static void -wrap_nearest_clamp_to_edge(const float s[4], unsigned size, - int icoord[4]) +wrap_nearest_clamp_to_edge(const float s[4], unsigned size, int icoord[4]) { uint ch; /* s limited to [min,max] */ @@ -168,8 +175,7 @@ wrap_nearest_clamp_to_edge(const float s[4], unsigned size, static void -wrap_nearest_clamp_to_border(const float s[4], unsigned size, - int icoord[4]) +wrap_nearest_clamp_to_border(const float s[4], unsigned size, int icoord[4]) { uint ch; /* s limited to [min,max] */ @@ -186,9 +192,9 @@ wrap_nearest_clamp_to_border(const float s[4], unsigned size, } } + static void -wrap_nearest_mirror_repeat(const float s[4], unsigned size, - int icoord[4]) +wrap_nearest_mirror_repeat(const float s[4], unsigned size, int icoord[4]) { uint ch; const float min = 1.0F / (2.0F * size); @@ -209,9 +215,9 @@ wrap_nearest_mirror_repeat(const float s[4], unsigned size, } } + static void -wrap_nearest_mirror_clamp(const float s[4], unsigned size, - int icoord[4]) +wrap_nearest_mirror_clamp(const float s[4], unsigned size, int icoord[4]) { uint ch; for (ch = 0; ch < 4; ch++) { @@ -227,9 +233,10 @@ wrap_nearest_mirror_clamp(const float s[4], unsigned size, } } + static void wrap_nearest_mirror_clamp_to_edge(const float s[4], unsigned size, - int icoord[4]) + int icoord[4]) { uint ch; /* s limited to [min,max] */ @@ -284,15 +291,15 @@ wrap_linear_repeat(const float s[4], unsigned size, int icoord0[4], int icoord1[4], float w[4]) { uint ch; - for (ch = 0; ch < 4; ch++) { float u = s[ch] * size - 0.5F; - icoord0[ch] = REMAINDER(util_ifloor(u), size); - icoord1[ch] = REMAINDER(icoord0[ch] + 1, size); - w[ch] = FRAC(u); + icoord0[ch] = repeat(util_ifloor(u), size); + icoord1[ch] = repeat(icoord0[ch] + 1, size); + w[ch] = frac(u); } } + static void wrap_linear_clamp(const float s[4], unsigned size, int icoord0[4], int icoord1[4], float w[4]) @@ -303,10 +310,11 @@ wrap_linear_clamp(const float s[4], unsigned size, u = u * size - 0.5f; icoord0[ch] = util_ifloor(u); icoord1[ch] = icoord0[ch] + 1; - w[ch] = FRAC(u); + w[ch] = frac(u); } } + static void wrap_linear_clamp_to_edge(const float s[4], unsigned size, int icoord0[4], int icoord1[4], float w[4]) @@ -321,10 +329,11 @@ wrap_linear_clamp_to_edge(const float s[4], unsigned size, icoord0[ch] = 0; if (icoord1[ch] >= (int) size) icoord1[ch] = size - 1; - w[ch] = FRAC(u); + w[ch] = frac(u); } } + static void wrap_linear_clamp_to_border(const float s[4], unsigned size, int icoord0[4], int icoord1[4], float w[4]) @@ -337,7 +346,7 @@ wrap_linear_clamp_to_border(const float s[4], unsigned size, u = u * size - 0.5f; icoord0[ch] = util_ifloor(u); icoord1[ch] = icoord0[ch] + 1; - w[ch] = FRAC(u); + w[ch] = frac(u); } } @@ -361,10 +370,11 @@ wrap_linear_mirror_repeat(const float s[4], unsigned size, icoord0[ch] = 0; if (icoord1[ch] >= (int) size) icoord1[ch] = size - 1; - w[ch] = FRAC(u); + w[ch] = frac(u); } } + static void wrap_linear_mirror_clamp(const float s[4], unsigned size, int icoord0[4], int icoord1[4], float w[4]) @@ -379,10 +389,11 @@ wrap_linear_mirror_clamp(const float s[4], unsigned size, u -= 0.5F; icoord0[ch] = util_ifloor(u); icoord1[ch] = icoord0[ch] + 1; - w[ch] = FRAC(u); + w[ch] = frac(u); } } + static void wrap_linear_mirror_clamp_to_edge(const float s[4], unsigned size, int icoord0[4], int icoord1[4], float w[4]) @@ -401,10 +412,11 @@ wrap_linear_mirror_clamp_to_edge(const float s[4], unsigned size, icoord0[ch] = 0; if (icoord1[ch] >= (int) size) icoord1[ch] = size - 1; - w[ch] = FRAC(u); + w[ch] = frac(u); } } + static void wrap_linear_mirror_clamp_to_border(const float s[4], unsigned size, int icoord0[4], int icoord1[4], float w[4]) @@ -423,7 +435,7 @@ wrap_linear_mirror_clamp_to_border(const float s[4], unsigned size, u -= 0.5F; icoord0[ch] = util_ifloor(u); icoord1[ch] = icoord0[ch] + 1; - w[ch] = FRAC(u); + w[ch] = frac(u); } } @@ -433,8 +445,7 @@ wrap_linear_mirror_clamp_to_border(const float s[4], unsigned size, * Only a subset of wrap modes supported. */ static void -wrap_nearest_unorm_clamp(const float s[4], unsigned size, - int icoord[4]) +wrap_nearest_unorm_clamp(const float s[4], unsigned size, int icoord[4]) { uint ch; for (ch = 0; ch < 4; ch++) { @@ -443,11 +454,13 @@ wrap_nearest_unorm_clamp(const float s[4], unsigned size, } } -/* Handles clamp_to_edge and clamp_to_border: + +/** + * Handles clamp_to_edge and clamp_to_border: */ static void wrap_nearest_unorm_clamp_to_border(const float s[4], unsigned size, - int icoord[4]) + int icoord[4]) { uint ch; for (ch = 0; ch < 4; ch++) { @@ -462,7 +475,7 @@ wrap_nearest_unorm_clamp_to_border(const float s[4], unsigned size, */ static void wrap_linear_unorm_clamp(const float s[4], unsigned size, - int icoord0[4], int icoord1[4], float w[4]) + int icoord0[4], int icoord1[4], float w[4]) { uint ch; for (ch = 0; ch < 4; ch++) { @@ -470,13 +483,14 @@ wrap_linear_unorm_clamp(const float s[4], unsigned size, float u = CLAMP(s[ch] - 0.5F, 0.0f, (float) size - 1.0f); icoord0[ch] = util_ifloor(u); icoord1[ch] = icoord0[ch] + 1; - w[ch] = FRAC(u); + w[ch] = frac(u); } } + static void -wrap_linear_unorm_clamp_to_border( const float s[4], unsigned size, - int icoord0[4], int icoord1[4], float w[4]) +wrap_linear_unorm_clamp_to_border(const float s[4], unsigned size, + int icoord0[4], int icoord1[4], float w[4]) { uint ch; for (ch = 0; ch < 4; ch++) { @@ -486,14 +500,12 @@ wrap_linear_unorm_clamp_to_border( const float s[4], unsigned size, icoord1[ch] = icoord0[ch] + 1; if (icoord1[ch] > (int) size - 1) icoord1[ch] = size - 1; - w[ch] = FRAC(u); + w[ch] = frac(u); } } - - /** * Examine the quad's texture coordinates to compute the partial * derivatives w.r.t X and Y, then compute lambda (level of detail). @@ -502,29 +514,23 @@ static float compute_lambda_1d(const struct sp_sampler_varient *samp, const float s[QUAD_SIZE], const float t[QUAD_SIZE], - const float p[QUAD_SIZE], - float lodbias) + const float p[QUAD_SIZE]) { const struct pipe_texture *texture = samp->texture; const struct pipe_sampler_state *sampler = samp->sampler; float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); - float rho = MAX2(dsdx, dsdy) * texture->width[0]; - float lambda; + float rho = MAX2(dsdx, dsdy) * texture->width0; - lambda = util_fast_log2(rho); - lambda += lodbias + sampler->lod_bias; - lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod); - - return lambda; + return util_fast_log2(rho); } + static float compute_lambda_2d(const struct sp_sampler_varient *samp, const float s[QUAD_SIZE], const float t[QUAD_SIZE], - const float p[QUAD_SIZE], - float lodbias) + const float p[QUAD_SIZE]) { const struct pipe_texture *texture = samp->texture; const struct pipe_sampler_state *sampler = samp->sampler; @@ -532,16 +538,11 @@ compute_lambda_2d(const struct sp_sampler_varient *samp, float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]); float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]); - float maxx = MAX2(dsdx, dsdy) * texture->width[0]; - float maxy = MAX2(dtdx, dtdy) * texture->height[0]; + float maxx = MAX2(dsdx, dsdy) * texture->width0; + float maxy = MAX2(dtdx, dtdy) * texture->height0; float rho = MAX2(maxx, maxy); - float lambda; - - lambda = util_fast_log2(rho); - lambda += lodbias + sampler->lod_bias; - lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod); - return lambda; + return util_fast_log2(rho); } @@ -549,8 +550,7 @@ static float compute_lambda_3d(const struct sp_sampler_varient *samp, const float s[QUAD_SIZE], const float t[QUAD_SIZE], - const float p[QUAD_SIZE], - float lodbias) + const float p[QUAD_SIZE]) { const struct pipe_texture *texture = samp->texture; const struct pipe_sampler_state *sampler = samp->sampler; @@ -560,31 +560,29 @@ compute_lambda_3d(const struct sp_sampler_varient *samp, float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]); float dpdx = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]); float dpdy = fabsf(p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT]); - float maxx = MAX2(dsdx, dsdy) * texture->width[0]; - float maxy = MAX2(dtdx, dtdy) * texture->height[0]; - float maxz = MAX2(dpdx, dpdy) * texture->depth[0]; - float rho, lambda; + float maxx = MAX2(dsdx, dsdy) * texture->width0; + float maxy = MAX2(dtdx, dtdy) * texture->height0; + float maxz = MAX2(dpdx, dpdy) * texture->depth0; + float rho; rho = MAX2(maxx, maxy); rho = MAX2(rho, maxz); - lambda = util_fast_log2(rho); - lambda += lodbias + sampler->lod_bias; - lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod); - - return lambda; + return util_fast_log2(rho); } - +/** + * Compute lambda for a vertex texture sampler. + * Since there aren't derivatives to use, just return 0. + */ static float compute_lambda_vert(const struct sp_sampler_varient *samp, const float s[QUAD_SIZE], const float t[QUAD_SIZE], - const float p[QUAD_SIZE], - float lodbias) + const float p[QUAD_SIZE]) { - return lodbias; + return 0.0f; } @@ -628,8 +626,8 @@ get_texel_2d(const struct sp_sampler_varient *samp, const struct pipe_texture *texture = samp->texture; unsigned level = addr.bits.level; - if (x < 0 || x >= (int) texture->width[level] || - y < 0 || y >= (int) texture->height[level]) { + if (x < 0 || x >= (int) u_minify(texture->width0, level) || + y < 0 || y >= (int) u_minify(texture->height0, level)) { return samp->sampler->border_color; } else { @@ -698,7 +696,7 @@ get_texel_quad_2d(const struct sp_sampler_varient *samp, */ static INLINE const float * get_texel_3d_no_border(const struct sp_sampler_varient *samp, - union tex_tile_address addr, int x, int y, int z) + union tex_tile_address addr, int x, int y, int z) { const struct softpipe_tex_cached_tile *tile; @@ -716,14 +714,14 @@ get_texel_3d_no_border(const struct sp_sampler_varient *samp, static INLINE const float * get_texel_3d(const struct sp_sampler_varient *samp, - union tex_tile_address addr, int x, int y, int z ) + union tex_tile_address addr, int x, int y, int z) { const struct pipe_texture *texture = samp->texture; unsigned level = addr.bits.level; - if (x < 0 || x >= (int) texture->width[level] || - y < 0 || y >= (int) texture->height[level] || - z < 0 || z >= (int) texture->depth[level]) { + if (x < 0 || x >= (int) u_minify(texture->width0, level) || + y < 0 || y >= (int) u_minify(texture->height0, level) || + z < 0 || z >= (int) u_minify(texture->depth0, level)) { return samp->sampler->border_color; } else { @@ -750,11 +748,12 @@ pot_level_size(unsigned base_pot, unsigned level) */ static INLINE void img_filter_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler, - const float s[QUAD_SIZE], - const float t[QUAD_SIZE], - const float p[QUAD_SIZE], - float lodbias, - float rgba[NUM_CHANNELS][QUAD_SIZE]) + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, + float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); unsigned j; @@ -768,7 +767,6 @@ img_filter_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler, addr.value = 0; addr.bits.level = samp->level; - for (j = 0; j < QUAD_SIZE; j++) { int c; @@ -788,18 +786,15 @@ img_filter_2d_linear_repeat_POT(struct tgsi_sampler *tgsi_sampler, /* Can we fetch all four at once: */ - if (x0 < xmax && y0 < ymax) - { + if (x0 < xmax && y0 < ymax) { get_texel_quad_2d_no_border_single_tile(samp, addr, x0, y0, tx); } - else - { + else { unsigned x1 = (x0 + 1) & (xpot - 1); unsigned y1 = (y0 + 1) & (ypot - 1); get_texel_quad_2d_no_border(samp, addr, x0, y0, x1, y1, tx); } - /* interpolate R, G, B, A */ for (c = 0; c < 4; c++) { rgba[c][j] = lerp_2d(xw, yw, @@ -815,7 +810,8 @@ img_filter_2d_nearest_repeat_POT(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); @@ -854,7 +850,8 @@ img_filter_2d_nearest_clamp_POT(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); @@ -896,12 +893,14 @@ img_filter_2d_nearest_clamp_POT(struct tgsi_sampler *tgsi_sampler, } } + static void img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); @@ -912,7 +911,7 @@ img_filter_1d_nearest(struct tgsi_sampler *tgsi_sampler, union tex_tile_address addr; level0 = samp->level; - width = texture->width[level0]; + width = u_minify(texture->width0, level0); assert(width > 0); @@ -936,7 +935,8 @@ img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); @@ -948,8 +948,8 @@ img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler, level0 = samp->level; - width = texture->width[level0]; - height = texture->height[level0]; + width = u_minify(texture->width0, level0); + height = u_minify(texture->height0, level0); assert(width > 0); assert(height > 0); @@ -969,20 +969,23 @@ img_filter_2d_nearest(struct tgsi_sampler *tgsi_sampler, } } -static inline union tex_tile_address face( union tex_tile_address addr, - unsigned face ) + +static INLINE union tex_tile_address +face(union tex_tile_address addr, unsigned face ) { addr.bits.face = face; return addr; } + static void img_filter_cube_nearest(struct tgsi_sampler *tgsi_sampler, - const float s[QUAD_SIZE], - const float t[QUAD_SIZE], - const float p[QUAD_SIZE], - float lodbias, - float rgba[NUM_CHANNELS][QUAD_SIZE]) + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, + float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); const struct pipe_texture *texture = samp->texture; @@ -992,10 +995,9 @@ img_filter_cube_nearest(struct tgsi_sampler *tgsi_sampler, int x[4], y[4]; union tex_tile_address addr; - level0 = samp->level; - width = texture->width[level0]; - height = texture->height[level0]; + width = u_minify(texture->width0, level0); + height = u_minify(texture->height0, level0); assert(width > 0); assert(height > 0); @@ -1021,7 +1023,8 @@ img_filter_3d_nearest(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); @@ -1032,9 +1035,9 @@ img_filter_3d_nearest(struct tgsi_sampler *tgsi_sampler, union tex_tile_address addr; level0 = samp->level; - width = texture->width[level0]; - height = texture->height[level0]; - depth = texture->depth[level0]; + width = u_minify(texture->width0, level0); + height = u_minify(texture->height0, level0); + depth = u_minify(texture->depth0, level0); assert(width > 0); assert(height > 0); @@ -1062,7 +1065,8 @@ img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); @@ -1073,9 +1077,8 @@ img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler, float xw[4]; /* weights */ union tex_tile_address addr; - level0 = samp->level; - width = texture->width[level0]; + width = u_minify(texture->width0, level0); assert(width > 0); @@ -1084,7 +1087,6 @@ img_filter_1d_linear(struct tgsi_sampler *tgsi_sampler, samp->linear_texcoord_s(s, width, x0, x1, xw); - for (j = 0; j < QUAD_SIZE; j++) { const float *tx0 = get_texel_2d(samp, addr, x0[j], 0); const float *tx1 = get_texel_2d(samp, addr, x1[j], 0); @@ -1103,7 +1105,8 @@ img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); @@ -1114,10 +1117,9 @@ img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler, float xw[4], yw[4]; /* weights */ union tex_tile_address addr; - level0 = samp->level; - width = texture->width[level0]; - height = texture->height[level0]; + width = u_minify(texture->width0, level0); + height = u_minify(texture->height0, level0); assert(width > 0); assert(height > 0); @@ -1147,11 +1149,12 @@ img_filter_2d_linear(struct tgsi_sampler *tgsi_sampler, static void img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler, - const float s[QUAD_SIZE], - const float t[QUAD_SIZE], - const float p[QUAD_SIZE], - float lodbias, - float rgba[NUM_CHANNELS][QUAD_SIZE]) + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, + float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); const struct pipe_texture *texture = samp->texture; @@ -1162,10 +1165,9 @@ img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler, float xw[4], yw[4]; /* weights */ union tex_tile_address addr; - level0 = samp->level; - width = texture->width[level0]; - height = texture->height[level0]; + width = u_minify(texture->width0, level0); + height = u_minify(texture->height0, level0); assert(width > 0); assert(height > 0); @@ -1199,7 +1201,8 @@ img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { const struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); @@ -1211,9 +1214,9 @@ img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler, union tex_tile_address addr; level0 = samp->level; - width = texture->width[level0]; - height = texture->height[level0]; - depth = texture->depth[level0]; + width = u_minify(texture->width0, level0); + height = u_minify(texture->height0, level0); + depth = u_minify(texture->depth0, level0); addr.value = 0; addr.bits.level = level0; @@ -1251,34 +1254,60 @@ img_filter_3d_linear(struct tgsi_sampler *tgsi_sampler, } +/* Calculate level of detail for every fragment. + * Note that lambda has already been biased by global LOD bias. + */ +static INLINE void +compute_lod(const struct pipe_sampler_state *sampler, + const float biased_lambda, + const float lodbias[QUAD_SIZE], + float lod[QUAD_SIZE]) +{ + uint i; - - + for (i = 0; i < QUAD_SIZE; i++) { + lod[i] = biased_lambda + lodbias[i]; + lod[i] = CLAMP(lod[i], sampler->min_lod, sampler->max_lod); + } +} static void mip_filter_linear(struct tgsi_sampler *tgsi_sampler, - const float s[QUAD_SIZE], - const float t[QUAD_SIZE], - const float p[QUAD_SIZE], - float lodbias, - float rgba[NUM_CHANNELS][QUAD_SIZE]) + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, + float rgba[NUM_CHANNELS][QUAD_SIZE]) { struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); const struct pipe_texture *texture = samp->texture; int level0; float lambda; + float lod[QUAD_SIZE]; - lambda = samp->compute_lambda(samp, s, t, p, lodbias); + if (control == tgsi_sampler_lod_bias) { + lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; + compute_lod(samp->sampler, lambda, c0, lod); + } else { + assert(control == tgsi_sampler_lod_explicit); + + memcpy(lod, c0, sizeof(lod)); + } + + /* XXX: Take into account all lod values. + */ + lambda = lod[0]; level0 = (int)lambda; if (lambda < 0.0) { samp->level = 0; - samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba ); + samp->mag_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); } else if (level0 >= texture->last_level) { samp->level = texture->last_level; - samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba ); + samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); } else { float levelBlend = lambda - level0; @@ -1287,10 +1316,10 @@ mip_filter_linear(struct tgsi_sampler *tgsi_sampler, int c,j; samp->level = level0; - samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba0 ); + samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba0); samp->level = level0+1; - samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba1 ); + samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba1); for (j = 0; j < QUAD_SIZE; j++) { for (c = 0; c < 4; c++) { @@ -1301,29 +1330,41 @@ mip_filter_linear(struct tgsi_sampler *tgsi_sampler, } - static void mip_filter_nearest(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); const struct pipe_texture *texture = samp->texture; float lambda; + float lod[QUAD_SIZE]; + + if (control == tgsi_sampler_lod_bias) { + lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; + compute_lod(samp->sampler, lambda, c0, lod); + } else { + assert(control == tgsi_sampler_lod_explicit); + + memcpy(lod, c0, sizeof(lod)); + } - lambda = samp->compute_lambda(samp, s, t, p, lodbias); + /* XXX: Take into account all lod values. + */ + lambda = lod[0]; if (lambda < 0.0) { samp->level = 0; - samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba ); + samp->mag_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); } else { samp->level = (int)(lambda + 0.5) ; samp->level = MIN2(samp->level, (int)texture->last_level); - samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba ); + samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); } #if 0 @@ -1341,23 +1382,39 @@ mip_filter_none(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); - float lambda = samp->compute_lambda(samp, s, t, p, lodbias); + float lambda; + float lod[QUAD_SIZE]; + + if (control == tgsi_sampler_lod_bias) { + lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; + compute_lod(samp->sampler, lambda, c0, lod); + } else { + assert(control == tgsi_sampler_lod_explicit); + + memcpy(lod, c0, sizeof(lod)); + } + + /* XXX: Take into account all lod values. + */ + lambda = lod[0]; if (lambda < 0.0) { - samp->mag_img_filter( tgsi_sampler, s, t, p, 0, rgba ); + samp->mag_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); } else { - samp->min_img_filter( tgsi_sampler, s, t, p, 0, rgba ); + samp->min_img_filter(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); } } -/* Specialized version of mip_filter_linear with hard-wired calls to +/** + * Specialized version of mip_filter_linear with hard-wired calls to * 2d lambda calculation and 2d_linear_repeat_POT img filters. */ static void @@ -1366,15 +1423,28 @@ mip_filter_linear_2d_linear_repeat_POT( const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); const struct pipe_texture *texture = samp->texture; int level0; float lambda; + float lod[QUAD_SIZE]; + + if (control == tgsi_sampler_lod_bias) { + lambda = samp->compute_lambda(samp, s, t, p) + samp->sampler->lod_bias; + compute_lod(samp->sampler, lambda, c0, lod); + } else { + assert(control == tgsi_sampler_lod_explicit); + + memcpy(lod, c0, sizeof(lod)); + } - lambda = compute_lambda_2d(samp, s, t, p, lodbias); + /* XXX: Take into account all lod values. + */ + lambda = lod[0]; level0 = (int)lambda; /* Catches both negative and large values of level0: @@ -1385,7 +1455,7 @@ mip_filter_linear_2d_linear_repeat_POT( else samp->level = texture->last_level; - img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba ); + img_filter_2d_linear_repeat_POT(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba); } else { float levelBlend = lambda - level0; @@ -1394,10 +1464,10 @@ mip_filter_linear_2d_linear_repeat_POT( int c,j; samp->level = level0; - img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba0 ); + img_filter_2d_linear_repeat_POT(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba0); samp->level = level0+1; - img_filter_2d_linear_repeat_POT( tgsi_sampler, s, t, p, 0, rgba1 ); + img_filter_2d_linear_repeat_POT(tgsi_sampler, s, t, p, NULL, tgsi_sampler_lod_bias, rgba1); for (j = 0; j < QUAD_SIZE; j++) { for (c = 0; c < 4; c++) { @@ -1409,14 +1479,16 @@ mip_filter_linear_2d_linear_repeat_POT( -/* Compare stage in the little sampling pipeline. +/** + * Do shadow/depth comparisons. */ static void sample_compare(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); @@ -1424,8 +1496,7 @@ sample_compare(struct tgsi_sampler *tgsi_sampler, int j, k0, k1, k2, k3; float val; - samp->mip_filter( tgsi_sampler, s, t, p, lodbias, rgba ); - + samp->mip_filter(tgsi_sampler, s, t, p, c0, control, rgba); /** * Compare texcoord 'p' (aka R) against texture value 'rgba[0]' @@ -1493,14 +1564,18 @@ sample_compare(struct tgsi_sampler *tgsi_sampler, } } -/* Calculate cube faces. + +/** + * Compute which cube face is referenced by each texcoord and put that + * info into the sampler faces[] array. Then sample the cube faces */ static void sample_cube(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], const float t[QUAD_SIZE], const float p[QUAD_SIZE], - float lodbias, + const float c0[QUAD_SIZE], + enum tgsi_sampler_control control, float rgba[NUM_CHANNELS][QUAD_SIZE]) { struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); @@ -1581,13 +1656,13 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, * is not active, this will point somewhere deeper into the * pipeline, eg. to mip_filter or even img_filter. */ - samp->compare(tgsi_sampler, ssss, tttt, NULL, lodbias, rgba); + samp->compare(tgsi_sampler, ssss, tttt, NULL, c0, control, rgba); } - -static wrap_nearest_func get_nearest_unorm_wrap( unsigned mode ) +static wrap_nearest_func +get_nearest_unorm_wrap(unsigned mode) { switch (mode) { case PIPE_TEX_WRAP_CLAMP: @@ -1602,7 +1677,8 @@ static wrap_nearest_func get_nearest_unorm_wrap( unsigned mode ) } -static wrap_nearest_func get_nearest_wrap( unsigned mode ) +static wrap_nearest_func +get_nearest_wrap(unsigned mode) { switch (mode) { case PIPE_TEX_WRAP_REPEAT: @@ -1627,7 +1703,9 @@ static wrap_nearest_func get_nearest_wrap( unsigned mode ) } } -static wrap_linear_func get_linear_unorm_wrap( unsigned mode ) + +static wrap_linear_func +get_linear_unorm_wrap(unsigned mode) { switch (mode) { case PIPE_TEX_WRAP_CLAMP: @@ -1641,7 +1719,9 @@ static wrap_linear_func get_linear_unorm_wrap( unsigned mode ) } } -static wrap_linear_func get_linear_wrap( unsigned mode ) + +static wrap_linear_func +get_linear_wrap(unsigned mode) { switch (mode) { case PIPE_TEX_WRAP_REPEAT: @@ -1666,7 +1746,9 @@ static wrap_linear_func get_linear_wrap( unsigned mode ) } } -static compute_lambda_func get_lambda_func( const union sp_sampler_key key ) + +static compute_lambda_func +get_lambda_func(const union sp_sampler_key key) { if (key.bits.processor == TGSI_PROCESSOR_VERTEX) return compute_lambda_vert; @@ -1685,9 +1767,11 @@ static compute_lambda_func get_lambda_func( const union sp_sampler_key key ) } } -static filter_func get_img_filter( const union sp_sampler_key key, - unsigned filter, - const struct pipe_sampler_state *sampler ) + +static filter_func +get_img_filter(const union sp_sampler_key key, + unsigned filter, + const struct pipe_sampler_state *sampler) { switch (key.bits.target) { case PIPE_TEXTURE_1D: @@ -1761,8 +1845,8 @@ sp_sampler_varient_bind_texture( struct sp_sampler_varient *samp, samp->texture = texture; samp->cache = tex_cache; - samp->xpot = util_unsigned_logbase2( texture->width[0] ); - samp->ypot = util_unsigned_logbase2( texture->height[0] ); + samp->xpot = util_unsigned_logbase2( texture->width0 ); + samp->ypot = util_unsigned_logbase2( texture->height0 ); samp->level = CLAMP((int) sampler->min_lod, 0, (int) texture->last_level); } @@ -1774,7 +1858,8 @@ sp_sampler_varient_destroy( struct sp_sampler_varient *samp ) } -/* Create a sampler varient for a given set of non-orthogonal state. Currently the +/** + * Create a sampler varient for a given set of non-orthogonal state. */ struct sp_sampler_varient * sp_create_sampler_varient( const struct pipe_sampler_state *sampler, @@ -1844,7 +1929,7 @@ sp_create_sampler_varient( const struct pipe_sampler_state *sampler, break; } - if (sampler->compare_mode != FALSE) { + if (sampler->compare_mode != PIPE_TEX_COMPARE_NONE) { samp->compare = sample_compare; } else { @@ -1871,9 +1956,3 @@ sp_create_sampler_varient( const struct pipe_sampler_state *sampler, return samp; } - - - - - -