From b4480285ed5098f1c862690ee105dd46f5e6cd1e Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 14 Aug 2007 11:00:35 -0600 Subject: [PATCH] tgsi_sampler->get_samples() now operates on a quad (returns 4 colors). Lambda/level-of-detail is also computed in get_samples() now. --- src/mesa/pipe/softpipe/sp_quad_fs.c | 2 +- src/mesa/pipe/softpipe/sp_tex_sample.c | 405 +++++++++++++++++++++------------ src/mesa/pipe/softpipe/sp_tex_sample.h | 7 +- src/mesa/pipe/tgsi/core/tgsi_exec.c | 87 +------ src/mesa/pipe/tgsi/core/tgsi_exec.h | 13 +- 5 files changed, 286 insertions(+), 228 deletions(-) diff --git a/src/mesa/pipe/softpipe/sp_quad_fs.c b/src/mesa/pipe/softpipe/sp_quad_fs.c index 70a80af..096385d 100644 --- a/src/mesa/pipe/softpipe/sp_quad_fs.c +++ b/src/mesa/pipe/softpipe/sp_quad_fs.c @@ -322,7 +322,7 @@ static void shade_begin(struct quad_stage *qs) for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { qss->samplers[i].state = &softpipe->sampler[i]; qss->samplers[i].texture = softpipe->texture[i]; - qss->samplers[i].get_sample = sp_get_sample; + qss->samplers[i].get_samples = sp_get_samples; qss->samplers[i].pipe = &softpipe->pipe; /* init cache info here */ qss->samplers[i].cache_x = diff --git a/src/mesa/pipe/softpipe/sp_tex_sample.c b/src/mesa/pipe/softpipe/sp_tex_sample.c index fb4f793..2005a3d 100644 --- a/src/mesa/pipe/softpipe/sp_tex_sample.c +++ b/src/mesa/pipe/softpipe/sp_tex_sample.c @@ -66,12 +66,12 @@ * optimization! If we find that's not true on some systems, convert * to a macro. */ -static INLINE GLfloat -lerp_2d(GLfloat a, GLfloat b, - GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11) +static INLINE float +lerp_2d(float a, float b, + float v00, float v10, float v01, float v11) { - const GLfloat temp0 = LERP(a, v00, v10); - const GLfloat temp1 = LERP(a, v01, v11); + const float temp0 = LERP(a, v00, v10); + const float temp1 = LERP(a, v01, v11); return LERP(b, temp0, temp1); } @@ -98,7 +98,7 @@ repeat_remainder(GLint a, GLint b) * \return integer texture index */ static INLINE GLint -nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size) +nearest_texcoord(GLuint wrapMode, float s, GLuint size) { GLint i; switch (wrapMode) { @@ -122,8 +122,8 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size) { /* 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; + const float min = 1.0F / (2.0F * size); + const float max = 1.0F - min; if (s < min) i = 0; else if (s > max) @@ -136,8 +136,8 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size) { /* s limited to [min,max] */ /* i limited to [-1, size] */ - const GLfloat min = -1.0F / (2.0F * size); - const GLfloat max = 1.0F - min; + const float min = -1.0F / (2.0F * size); + const float max = 1.0F - min; if (s <= min) i = -1; else if (s >= max) @@ -148,14 +148,14 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size) return i; case PIPE_TEX_WRAP_MIRROR_REPEAT: { - const GLfloat min = 1.0F / (2.0F * size); - const GLfloat max = 1.0F - min; + const float min = 1.0F / (2.0F * size); + const float max = 1.0F - min; const GLint flr = IFLOOR(s); - GLfloat u; + float u; if (flr & 1) - u = 1.0F - (s - (GLfloat) flr); + u = 1.0F - (s - (float) flr); else - u = s - (GLfloat) flr; + u = s - (float) flr; if (u < min) i = 0; else if (u > max) @@ -168,7 +168,7 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size) { /* s limited to [0,1] */ /* i limited to [0,size-1] */ - const GLfloat u = FABSF(s); + const float u = FABSF(s); if (u <= 0.0F) i = 0; else if (u >= 1.0F) @@ -181,9 +181,9 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size) { /* 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; - const GLfloat u = FABSF(s); + const float min = 1.0F / (2.0F * size); + const float max = 1.0F - min; + const float u = FABSF(s); if (u < min) i = 0; else if (u > max) @@ -196,9 +196,9 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size) { /* 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; - const GLfloat u = FABSF(s); + const float min = -1.0F / (2.0F * size); + const float max = 1.0F - min; + const float u = FABSF(s); if (u < min) i = -1; else if (u > max) @@ -224,10 +224,10 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size) * \param a returns blend factor/weight between texture indexes */ static INLINE void -linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size, - GLint *i0, GLint *i1, GLfloat *a) +linear_texcoord(GLuint wrapMode, float s, GLuint size, + GLint *i0, GLint *i1, float *a) { - GLfloat u; + float u; switch (wrapMode) { case PIPE_TEX_WRAP_REPEAT: u = s * size - 0.5F; @@ -238,7 +238,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size, if (s <= 0.0F) u = 0.0F; else if (s >= 1.0F) - u = (GLfloat) size; + u = (float) size; else u = s * size; u -= 0.5F; @@ -249,7 +249,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size, if (s <= 0.0F) u = 0.0F; else if (s >= 1.0F) - u = (GLfloat) size; + u = (float) size; else u = s * size; u -= 0.5F; @@ -262,8 +262,8 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size, break; case PIPE_TEX_WRAP_CLAMP_TO_BORDER: { - const GLfloat min = -1.0F / (2.0F * size); - const GLfloat max = 1.0F - min; + const float min = -1.0F / (2.0F * size); + const float max = 1.0F - min; if (s <= min) u = min * size; else if (s >= max) @@ -279,9 +279,9 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size, { const GLint flr = IFLOOR(s); if (flr & 1) - u = 1.0F - (s - (GLfloat) flr); + u = 1.0F - (s - (float) flr); else - u = s - (GLfloat) flr; + u = s - (float) flr; u = (u * size) - 0.5F; *i0 = IFLOOR(u); *i1 = *i0 + 1; @@ -294,7 +294,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size, case PIPE_TEX_WRAP_MIRROR_CLAMP: u = FABSF(s); if (u >= 1.0F) - u = (GLfloat) size; + u = (float) size; else u *= size; u -= 0.5F; @@ -304,7 +304,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size, case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: u = FABSF(s); if (u >= 1.0F) - u = (GLfloat) size; + u = (float) size; else u *= size; u -= 0.5F; @@ -317,8 +317,8 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size, break; case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: { - const GLfloat min = -1.0F / (2.0F * size); - const GLfloat max = 1.0F - min; + const float min = -1.0F / (2.0F * size); + const float max = 1.0F - min; u = FABSF(s); if (u <= min) u = min * size; @@ -339,7 +339,8 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size, static GLuint -choose_cube_face(const GLfloat texcoord[4], GLfloat newCoord[4]) +choose_cube_face(float rx, float ry, float rz, + float newCoord[4]) { /* major axis @@ -352,12 +353,9 @@ choose_cube_face(const GLfloat texcoord[4], GLfloat newCoord[4]) +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz */ - const GLfloat rx = texcoord[0]; - const GLfloat ry = texcoord[1]; - const GLfloat rz = texcoord[2]; - const GLfloat arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz); + const float arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz); GLuint face; - GLfloat sc, tc, ma; + float sc, tc, ma; if (arx > ary && arx > arz) { if (rx >= 0.0F) { @@ -409,9 +407,62 @@ choose_cube_face(const GLfloat texcoord[4], GLfloat newCoord[4]) } +/** + * Examine the quad's texture coordinates to compute the partial + * derivatives w.r.t X and Y, then compute lambda (level of detail). + * + * This is only done for fragment shaders, not vertex shaders. + */ +static float +compute_lambda(struct tgsi_sampler *sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE]) +{ + float rho, lambda; + + assert(s); + { + float dsdx = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]; + float dsdy = s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]; + dsdx = FABSF(dsdx); + dsdy = FABSF(dsdy); + rho = MAX2(dsdx, dsdy) * sampler->texture->width0; + } + if (t) { + float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]; + float dtdy = t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]; + float max; + dtdx = FABSF(dtdx); + dtdy = FABSF(dtdy); + max = MAX2(dtdx, dtdy) * sampler->texture->height0; + rho = MAX2(rho, max); + } + if (p) { + float dpdx = p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]; + float dpdy = p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT]; + float max; + dpdx = FABSF(dpdx); + dpdy = FABSF(dpdy); + max = MAX2(dpdx, dpdy) * sampler->texture->depth0; + rho = MAX2(rho, max); + } + + lambda = LOG2(rho); + + lambda += sampler->state->lod_bias; + lambda = CLAMP(lambda, sampler->state->min_lod, sampler->state->max_lod); + + return lambda; +} + + static void -sp_get_sample_1d(struct tgsi_sampler *sampler, - const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4]) +sp_get_samples_1d(struct tgsi_sampler *sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + float rgba[NUM_CHANNELS][QUAD_SIZE]) { struct pipe_context *pipe = (struct pipe_context *) sampler->pipe; struct pipe_surface *ps @@ -420,26 +471,40 @@ sp_get_sample_1d(struct tgsi_sampler *sampler, switch (sampler->state->min_img_filter) { case PIPE_TEX_FILTER_NEAREST: { - GLint x; - x = nearest_texcoord(sampler->state->wrap_s, strq[0], - sampler->texture->width0); - ps->get_tile(ps, x, 0, 1, 1, rgba); + GLuint j; + for (j = 0; j < QUAD_SIZE; j++) { + GLint x = nearest_texcoord(sampler->state->wrap_s, s[j], + sampler->texture->width0); + float texel[4]; + ps->get_tile(ps, x, 0, 1, 1, texel); + rgba[0][j] = texel[0]; + rgba[1][j] = texel[1]; + rgba[2][j] = texel[2]; + rgba[3][j] = texel[3]; + } } break; case PIPE_TEX_FILTER_LINEAR: { - GLfloat t0[4], t1[4]; - GLint x0, x1; - GLfloat a; - linear_texcoord(sampler->state->wrap_s, strq[0], - sampler->texture->width0, &x0, &x1, &a); - ps->get_tile(ps, x0, 0, 1, 1, t0); - ps->get_tile(ps, x1, 0, 1, 1, t1); - - rgba[0] = LERP(a, t0[0], t1[0]); - rgba[1] = LERP(a, t0[1], t1[1]); - rgba[2] = LERP(a, t0[2], t1[2]); - rgba[3] = LERP(a, t0[3], t1[3]); + GLuint j; + for (j = 0; j < QUAD_SIZE; j++) { + float t0[4], t1[4], texel[4]; + GLint x0, x1; + float a; + linear_texcoord(sampler->state->wrap_s, s[j], + sampler->texture->width0, &x0, &x1, &a); + ps->get_tile(ps, x0, 0, 1, 1, t0); + ps->get_tile(ps, x1, 0, 1, 1, t1); + + texel[0] = LERP(a, t0[0], t1[0]); + texel[1] = LERP(a, t0[1], t1[1]); + texel[2] = LERP(a, t0[2], t1[2]); + texel[3] = LERP(a, t0[3], t1[3]); + rgba[0][j] = texel[0]; + rgba[1][j] = texel[1]; + rgba[2][j] = texel[2]; + rgba[3][j] = texel[3]; + } } break; default: @@ -448,7 +513,7 @@ sp_get_sample_1d(struct tgsi_sampler *sampler, } static GLuint -choose_mipmap_level(struct tgsi_sampler *sampler, GLfloat lambda) +choose_mipmap_level(struct tgsi_sampler *sampler, float lambda) { if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { return 0; @@ -463,7 +528,68 @@ choose_mipmap_level(struct tgsi_sampler *sampler, GLfloat lambda) /** - * Called via tgsi_sampler::get_sample() + * Load the texture cache with a new texture tile. + */ +static void +cache_tex_tile(struct tgsi_sampler *sampler, + unsigned face, unsigned level, unsigned zslice, int cx, int cy) +{ + struct pipe_context *pipe = (struct pipe_context *) sampler->pipe; + struct pipe_surface *ps + = pipe->get_tex_surface(pipe, sampler->texture, face, level, zslice); + assert(ps->width == sampler->texture->level[level].width); + assert(ps->height == sampler->texture->level[level].height); + sampler->cache_level = level; + sampler->cache_x = cx; + sampler->cache_y = cy; + ps->get_tile(ps, + cx * SAMPLER_CACHE_SIZE, + cy * SAMPLER_CACHE_SIZE, + SAMPLER_CACHE_SIZE, SAMPLER_CACHE_SIZE, + (float *) sampler->cache); +} + + +/** + * Get a texel from a texture. + * \param face the cube face in 0..5 + * \param level the mipmap level + * \param zslize which slice of a 3D texture + * \param x the x coord of texel within 2D image + * \param y the y coord of texel within 2D image + * \param rgba the quad to put the texel/color into + * \param j which element of the rgba quad to write to + */ +static void +get_texel(struct tgsi_sampler *sampler, + unsigned face, unsigned level, unsigned zslice, int x, int y, + float rgba[NUM_CHANNELS][QUAD_SIZE], GLuint j) +{ + int cx = x / SAMPLER_CACHE_SIZE; + int cy = y / SAMPLER_CACHE_SIZE; + + if (cx != sampler->cache_x || cy != sampler->cache_y || + level != sampler->cache_level) { + cache_tex_tile(sampler, face, level, zslice, cx, cy); + printf("cache miss (%d, %d)\n", x, y); + } + else { + printf("cache hit (%d, %d)\n", x, y); + } + + /* get texel from cache */ + cx = x % SAMPLER_CACHE_SIZE; + cy = y % SAMPLER_CACHE_SIZE; + rgba[0][j] = sampler->cache[cy][cx][0]; + rgba[1][j] = sampler->cache[cy][cx][1]; + rgba[2][j] = sampler->cache[cy][cx][2]; + rgba[3][j] = sampler->cache[cy][cx][3]; +} + + + +/** + * Called via tgsi_sampler::get_samples() * Use the sampler's state setting to get a filtered RGBA value * from the sampler's texture (mipmap tree). * @@ -475,87 +601,62 @@ choose_mipmap_level(struct tgsi_sampler *sampler, GLfloat lambda) * a new tgsi_sampler object for each state combo it finds.... */ static void -sp_get_sample_2d(struct tgsi_sampler *sampler, - const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4]) +sp_get_samples_2d(struct tgsi_sampler *sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + float rgba[NUM_CHANNELS][QUAD_SIZE]) { - struct pipe_context *pipe = (struct pipe_context *) sampler->pipe; - GLuint filter; - GLint level0; - - if (lambda < 0.0) - filter = sampler->state->mag_img_filter; - else - filter = sampler->state->min_img_filter; + GLuint j, imgFilter; + int level0, width, height; + + /* compute level0 and imgFilter */ + switch (sampler->state->min_mip_filter) { + case PIPE_TEX_MIPFILTER_NONE: + imgFilter = sampler->state->mag_img_filter; + level0 = 0; + assert(sampler->state->min_img_filter == + sampler->state->mag_img_filter); + break; + default: + { + float lambda = compute_lambda(sampler, s, t, p); + if (lambda < 0.0) + imgFilter = sampler->state->mag_img_filter; + else + imgFilter = sampler->state->min_img_filter; + level0 = choose_mipmap_level(sampler, lambda); + } + } - level0 = choose_mipmap_level(sampler, lambda); + width = sampler->texture->level[level0].width; + height = sampler->texture->level[level0].height; - assert(sampler->texture->level[level0].width); + assert(width > 0); - switch (filter) { + switch (imgFilter) { case PIPE_TEX_FILTER_NEAREST: - { - GLint x = nearest_texcoord(sampler->state->wrap_s, strq[0], - sampler->texture->level[level0].width); - GLint y = nearest_texcoord(sampler->state->wrap_t, strq[1], - sampler->texture->level[level0].height); - GLint cx = x / SAMPLER_CACHE_SIZE; - GLint cy = y / SAMPLER_CACHE_SIZE; - if (cx != sampler->cache_x || cy != sampler->cache_y || - level0 != sampler->cache_level) { - /* cache miss, replace cache with new tile */ - struct pipe_surface *ps - = pipe->get_tex_surface(pipe, sampler->texture, 0, level0, 0); - assert(ps->width == sampler->texture->level[level0].width); - assert(ps->height == sampler->texture->level[level0].height); - sampler->cache_level = level0; - sampler->cache_x = cx; - sampler->cache_y = cy; - ps->get_tile(ps, - cx * SAMPLER_CACHE_SIZE, - cy * SAMPLER_CACHE_SIZE, - SAMPLER_CACHE_SIZE, SAMPLER_CACHE_SIZE, - (GLfloat *) sampler->cache); - /*printf("cache miss (%d, %d)\n", x, y);*/ - } - else { - /*printf("cache hit (%d, %d)\n", x, y);*/ - } - /* get texel from cache */ - cx = x % SAMPLER_CACHE_SIZE; - cy = y % SAMPLER_CACHE_SIZE; - COPY_4V(rgba, sampler->cache[cy][cx]); + for (j = 0; j < QUAD_SIZE; j++) { + int x = nearest_texcoord(sampler->state->wrap_s, s[j], width); + int y = nearest_texcoord(sampler->state->wrap_t, t[j], height); + get_texel(sampler, 0, level0, 0, x, y, rgba, j); } break; case PIPE_TEX_FILTER_LINEAR: - { - GLfloat t00[4], t01[4], t10[4], t11[4]; - GLint x0, y0, x1, y1; - GLfloat a, b; - struct pipe_surface *ps - = pipe->get_tex_surface(pipe, sampler->texture, 0, level0, 0); - - linear_texcoord(sampler->state->wrap_s, strq[0], - sampler->texture->width0, &x0, &x1, &a); - linear_texcoord(sampler->state->wrap_t, strq[1], - sampler->texture->height0, &y0, &y1, &b); - ps->get_tile(ps, x0, y0, 1, 1, t00); - ps->get_tile(ps, x1, y0, 1, 1, t10); - ps->get_tile(ps, x0, y1, 1, 1, t01); - ps->get_tile(ps, x1, y1, 1, 1, t11); - - rgba[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]); - rgba[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]); - rgba[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]); - rgba[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]); - } - break; - /* - { - GLuint level0, level1; - level0 = choose_mipmap_level(sampler, lambda); + for (j = 0; j < QUAD_SIZE; j++) { + float tx[4][4], a, b; + int x0, y0, x1, y1, c; + linear_texcoord(sampler->state->wrap_s, s[j], width, &x0, &x1, &a); + linear_texcoord(sampler->state->wrap_t, t[j], height, &y0, &y1, &b); + get_texel(sampler, 0, level0, 0, x0, y0, tx, 0); + get_texel(sampler, 0, level0, 0, x1, y0, tx, 1); + get_texel(sampler, 0, level0, 0, x0, y1, tx, 2); + get_texel(sampler, 0, level0, 0, x1, y1, tx, 3); + for (c = 0; c < 4; c++) { + rgba[c][j] = lerp_2d(a, b, tx[c][0], tx[c][1], tx[c][2], tx[c][3]); + } } break; - */ default: assert(0); } @@ -563,40 +664,52 @@ sp_get_sample_2d(struct tgsi_sampler *sampler, static void -sp_get_sample_3d(struct tgsi_sampler *sampler, - const GLfloat strq[4], GLfloat lamba, GLfloat rgba[4]) +sp_get_samples_3d(struct tgsi_sampler *sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + float rgba[NUM_CHANNELS][QUAD_SIZE]) { /* get/map pipe_surfaces corresponding to 3D tex slices */ } static void -sp_get_sample_cube(struct tgsi_sampler *sampler, - const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4]) +sp_get_samples_cube(struct tgsi_sampler *sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + float rgba[NUM_CHANNELS][QUAD_SIZE]) { - GLfloat st[4]; - GLuint face = choose_cube_face(strq, st); - - /* get/map surface corresponding to the face */ + GLuint j; + for (j = 0; j < QUAD_SIZE; j++) { + float st[4]; + GLuint face = choose_cube_face(s[j], t[j], p[j], st); + (void) face; + /* get/map surface corresponding to the face */ + } } void -sp_get_sample(struct tgsi_sampler *sampler, - const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4]) +sp_get_samples(struct tgsi_sampler *sampler, + const float s[QUAD_SIZE], + const float t[QUAD_SIZE], + const float p[QUAD_SIZE], + float rgba[NUM_CHANNELS][QUAD_SIZE]) { switch (sampler->texture->target) { case GL_TEXTURE_1D: - sp_get_sample_1d(sampler, strq, lambda, rgba); + sp_get_samples_1d(sampler, s, t, p, rgba); break; case GL_TEXTURE_2D: - sp_get_sample_2d(sampler, strq, lambda, rgba); + sp_get_samples_2d(sampler, s, t, p, rgba); break; case GL_TEXTURE_3D: - sp_get_sample_3d(sampler, strq, lambda, rgba); + sp_get_samples_3d(sampler, s, t, p, rgba); break; case GL_TEXTURE_CUBE_MAP: - sp_get_sample_cube(sampler, strq, lambda, rgba); + sp_get_samples_cube(sampler, s, t, p, rgba); break; default: assert(0); diff --git a/src/mesa/pipe/softpipe/sp_tex_sample.h b/src/mesa/pipe/softpipe/sp_tex_sample.h index 55ae490..417752d 100644 --- a/src/mesa/pipe/softpipe/sp_tex_sample.h +++ b/src/mesa/pipe/softpipe/sp_tex_sample.h @@ -6,8 +6,11 @@ struct tgsi_sampler; extern void -sp_get_sample(struct tgsi_sampler *sampler, - const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4]); +sp_get_samples(struct tgsi_sampler *sampler, + const GLfloat s[QUAD_SIZE], + const GLfloat t[QUAD_SIZE], + const GLfloat p[QUAD_SIZE], + GLfloat rgba[NUM_CHANNELS][QUAD_SIZE]); #endif /* SP_TEX_SAMPLE_H */ diff --git a/src/mesa/pipe/tgsi/core/tgsi_exec.c b/src/mesa/pipe/tgsi/core/tgsi_exec.c index 64d413b..03b3b49 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_exec.c +++ b/src/mesa/pipe/tgsi/core/tgsi_exec.c @@ -1034,44 +1034,6 @@ exec_kil (struct tgsi_exec_machine *mach, } -static GLfloat -compute_lambda(struct tgsi_sampler *sampler, - const union tgsi_exec_channel *s, - const union tgsi_exec_channel *t, - const union tgsi_exec_channel *p) -{ - GLfloat rho, lambda; - - assert(s); - { - GLfloat dsdx = s->f[TILE_BOTTOM_RIGHT] - s->f[TILE_BOTTOM_LEFT]; - GLfloat dsdy = s->f[TILE_TOP_LEFT] - s->f[TILE_BOTTOM_LEFT]; - dsdx = FABSF(dsdx); - dsdy = FABSF(dsdy); - rho = MAX2(dsdx, dsdy) * sampler->texture->width0; - } - if (t) { - GLfloat dtdx = t->f[TILE_BOTTOM_RIGHT] - t->f[TILE_BOTTOM_LEFT]; - GLfloat dtdy = t->f[TILE_TOP_LEFT] - t->f[TILE_BOTTOM_LEFT]; - GLfloat max; - dtdx = FABSF(dtdx); - dtdy = FABSF(dtdy); - max = MAX2(dtdx, dtdy) * sampler->texture->height0; - rho = MAX2(rho, max); - } - if (p) { - GLfloat dpdx = p->f[TILE_BOTTOM_RIGHT] - p->f[TILE_BOTTOM_LEFT]; - GLfloat dpdy = p->f[TILE_TOP_LEFT] - p->f[TILE_BOTTOM_LEFT]; - GLfloat max; - dpdx = FABSF(dpdx); - dpdy = FABSF(dpdy); - max = MAX2(dpdx, dpdy) * sampler->texture->depth0; - rho = MAX2(rho, max); - } - - lambda = LOG2(rho); - return lambda; -} /* @@ -1079,44 +1041,24 @@ compute_lambda(struct tgsi_sampler *sampler, */ static void fetch_texel( struct tgsi_sampler *sampler, - GLfloat lambda, const union tgsi_exec_channel *s, const union tgsi_exec_channel *t, const union tgsi_exec_channel *p, - GLuint unit, union tgsi_exec_channel *r, union tgsi_exec_channel *g, union tgsi_exec_channel *b, union tgsi_exec_channel *a ) { - GLuint fragment_index; - GLfloat stpq[4][4]; - - for (fragment_index = 0; fragment_index < 4; fragment_index++) { - stpq[fragment_index][0] = s->f[fragment_index]; - if (t) - stpq[fragment_index][1] = t->f[fragment_index]; - if (p) - stpq[fragment_index][2] = p->f[fragment_index]; - } + GLuint j; + GLfloat rgba[NUM_CHANNELS][QUAD_SIZE]; - lambda += sampler->state->lod_bias; - lambda = CLAMP(lambda, sampler->state->min_lod, sampler->state->max_lod); - - /* XXX: Use the same lambda value throughout the tile. Could - * end up with four unique values by recalculating partial - * derivs in the other row and column, and calculating lambda - * using the dx and dy values appropriate for each fragment in - * the tile. - */ - - for (fragment_index = 0; fragment_index < 4; fragment_index++) { - GLfloat rgba[4]; - sampler->get_sample(sampler, stpq[fragment_index], lambda, rgba); - r->f[fragment_index] = rgba[0]; - g->f[fragment_index] = rgba[1]; - b->f[fragment_index] = rgba[2]; - a->f[fragment_index] = rgba[3]; + sampler->get_samples(sampler, s->f, t->f, p->f, rgba); + + for (j = 0; j < 4; j++) { + r->f[j] = rgba[0][j]; + g->f[j] = rgba[1][j]; + b->f[j] = rgba[2][j]; + a->f[j] = rgba[3][j]; } } @@ -1647,7 +1589,6 @@ exec_instruction( case TGSI_OPCODE_TEX: { const GLuint unit = inst->FullSrcRegisters[1].SrcRegister.Index; - GLfloat lambda; switch (inst->InstructionExtTexture.Texture) { case TGSI_TEXTURE_1D: @@ -1666,10 +1607,8 @@ exec_instruction( assert (0); } - lambda = compute_lambda(&mach->Samplers[unit], &r[0], NULL, NULL); - fetch_texel(&mach->Samplers[unit], lambda, + fetch_texel(&mach->Samplers[unit], &r[0], NULL, NULL, - inst->FullSrcRegisters[1].SrcRegister.Index, &r[0], &r[1], &r[2], &r[3]); break; @@ -1693,11 +1632,8 @@ exec_instruction( assert (0); } - lambda = compute_lambda(&mach->Samplers[unit], &r[0], &r[1], NULL); fetch_texel(&mach->Samplers[unit], - lambda, &r[0], &r[1], NULL, - inst->FullSrcRegisters[1].SrcRegister.Index, &r[0], &r[1], &r[2], &r[3]); break; @@ -1723,11 +1659,8 @@ exec_instruction( assert (0); } - lambda = compute_lambda(&mach->Samplers[unit], &r[0], &r[1], &r[2]); fetch_texel(&mach->Samplers[unit], - lambda, &r[0], &r[1], &r[2], - inst->FullSrcRegisters[1].SrcRegister.Index, &r[0], &r[1], &r[2], &r[3]); break; diff --git a/src/mesa/pipe/tgsi/core/tgsi_exec.h b/src/mesa/pipe/tgsi/core/tgsi_exec.h index 01dd7f1..4e6fef5 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_exec.h +++ b/src/mesa/pipe/tgsi/core/tgsi_exec.h @@ -23,12 +23,21 @@ struct tgsi_exec_vector #define SAMPLER_CACHE_SIZE 8 +#define NUM_CHANNELS 4 /* R,G,B,A */ +#ifndef QUAD_SIZE +#define QUAD_SIZE 4 /* 4 pixel/quad */ +#endif + struct tgsi_sampler { const struct pipe_sampler_state *state; struct pipe_mipmap_tree *texture; - void (*get_sample)(struct tgsi_sampler *sampler, - const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4]); + /** Get samples for four fragments in a quad */ + void (*get_samples)(struct tgsi_sampler *sampler, + const GLfloat s[QUAD_SIZE], + const GLfloat t[QUAD_SIZE], + const GLfloat p[QUAD_SIZE], + GLfloat rgba[NUM_CHANNELS][QUAD_SIZE]); void *pipe; /*XXX temporary*/ GLint cache_x, cache_y, cache_level; -- 2.7.4