diff options
author | Brian Paul <brianp@vmware.com> | 2010-02-13 17:47:23 -0700 |
---|---|---|
committer | Brian Paul <brianp@vmware.com> | 2010-02-13 17:47:23 -0700 |
commit | 85425b3b609c480cd024b217b1efd0b9153bed58 (patch) | |
tree | bebde60f7f56fc494ca48cf1283bea83178776a9 /src | |
parent | b30898f4ab533085d97a33638ad0a1cf9ddb1d67 (diff) |
softpipe: fix broken cubemap / mipmap selection code
This is a quick-fix for the time being...
The per-face mipmap LOD computation was invalid at cube edges. In
mip_filter_nearest/linear() we were trying to compute LOD using
texcoords that were sometimes indexes into different cube faces.
The subtraction used to compute the partial derivatives basically
gave random values, so the LOD was unpredictable. This fix simply
uses the same cube face for all four pixels in the quad. The per-
face texcoords all reference the same cube face so the partial
deriviates are computed properly.
A more elaborate fix would involve computing the LOD at the same
time as we choose the cube faces. But for now, this solution works
well and allows the piglit/cubemap test to pass.
(cherry picked from commit 1ff9cd5079b095d7050edb8dc6a7e5b8cad36e1e)
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/softpipe/sp_tex_sample.c | 99 |
1 files changed, 71 insertions, 28 deletions
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index 473ec3e150..824d8d12b0 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -1327,6 +1327,11 @@ mip_filter_linear(struct tgsi_sampler *tgsi_sampler, } +/** + * Compute nearest mipmap level from texcoords. + * Then sample the texture level for four elements of a quad. + * \param c0 the LOD bias factors, or absolute LODs (depending on control) + */ static void mip_filter_nearest(struct tgsi_sampler *tgsi_sampler, const float s[QUAD_SIZE], @@ -1563,8 +1568,8 @@ sample_compare(struct tgsi_sampler *tgsi_sampler, /** - * Compute which cube face is referenced by each texcoord and put that - * info into the sampler faces[] array. Then sample the cube faces + * Use 3D texcoords to choose a cube face, then sample the 2D cube faces. + * Put face info into the sampler faces[] array. */ static void sample_cube(struct tgsi_sampler *tgsi_sampler, @@ -1578,11 +1583,12 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, struct sp_sampler_varient *samp = sp_sampler_varient(tgsi_sampler); unsigned j; float ssss[4], tttt[4]; + unsigned face; /* major axis - direction target sc tc ma - ---------- ------------------------------- --- --- --- + direction target sc tc ma + ---------- ------------------------------- --- --- --- +rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx -rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx +ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry @@ -1590,56 +1596,93 @@ sample_cube(struct tgsi_sampler *tgsi_sampler, +rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz -rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz */ - for (j = 0; j < QUAD_SIZE; j++) { - float rx = s[j]; - float ry = t[j]; - float rz = p[j]; + + /* First choose the cube face. + * Use the same cube face for all four pixels in the quad. + * + * This isn't ideal, but if we want to use a different cube face + * per pixel in the quad, we'd have to also compute the per-face + * LOD here too. That's because the four post-face-selection + * texcoords are no longer related to each other (they're + * per-face!) so we can't use subtraction to compute the partial + * deriviates to compute the LOD. Doing so (near cube edges + * anyway) gives us pretty much random values. + */ + { + /* use the average of the four pixel's texcoords to choose the face */ + const float rx = 0.25 * (s[0] + s[1] + s[2] + s[3]); + const float ry = 0.25 * (t[0] + t[1] + t[2] + t[3]); + const float rz = 0.25 * (p[0] + p[1] + p[2] + p[3]); const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); - unsigned face; - float sc, tc, ma; if (arx >= ary && arx >= arz) { if (rx >= 0.0F) { face = PIPE_TEX_FACE_POS_X; - sc = -rz; - tc = -ry; - ma = arx; } else { face = PIPE_TEX_FACE_NEG_X; - sc = rz; - tc = -ry; - ma = arx; } } else if (ary >= arx && ary >= arz) { if (ry >= 0.0F) { face = PIPE_TEX_FACE_POS_Y; - sc = rx; - tc = rz; - ma = ary; } else { face = PIPE_TEX_FACE_NEG_Y; - sc = rx; - tc = -rz; - ma = ary; } } else { if (rz > 0.0F) { face = PIPE_TEX_FACE_POS_Z; - sc = rx; - tc = -ry; - ma = arz; } else { face = PIPE_TEX_FACE_NEG_Z; - sc = -rx; - tc = -ry; - ma = arz; } } + } + + /* Now compute the 2D _face_ texture coords from the + * 3D _cube_ texture coords. + */ + for (j = 0; j < QUAD_SIZE; j++) { + const float rx = s[j], ry = t[j], rz = p[j]; + const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz); + float sc, tc, ma; + + switch (face) { + case PIPE_TEX_FACE_POS_X: + sc = -rz; + tc = -ry; + ma = arx; + break; + case PIPE_TEX_FACE_NEG_X: + sc = rz; + tc = -ry; + ma = arx; + break; + case PIPE_TEX_FACE_POS_Y: + sc = rx; + tc = rz; + ma = ary; + break; + case PIPE_TEX_FACE_NEG_Y: + sc = rx; + tc = -rz; + ma = ary; + break; + case PIPE_TEX_FACE_POS_Z: + sc = rx; + tc = -ry; + ma = arz; + break; + case PIPE_TEX_FACE_NEG_Z: + sc = -rx; + tc = -ry; + ma = arz; + break; + default: + assert(0 && "bad cube face"); + } { const float ima = 1.0 / ma; |