aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2009-11-14 23:27:20 +0100
committerCorbin Simpson <[email protected]>2009-11-20 17:58:13 -0800
commitb7078a88119e248b0196f7446abe029c22f1ee28 (patch)
tree7a52ddadbaca3266017bc818cb7598f0b5c12ff5
parent1c181a7eff96816b5d72ea5daab5818eef0ebc60 (diff)
r300g: add texture lod clamping
These now work: piglit/lodclamp piglit/levelclamp
-rw-r--r--src/gallium/drivers/r300/r300_context.h4
-rw-r--r--src/gallium/drivers/r300/r300_emit.c11
-rw-r--r--src/gallium/drivers/r300/r300_reg.h5
-rw-r--r--src/gallium/drivers/r300/r300_state.c5
-rw-r--r--src/gallium/drivers/r300/r300_texture.c3
5 files changed, 23 insertions, 5 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index f954ba7f9aa..60ef415caa9 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -92,6 +92,10 @@ struct r300_sampler_state {
uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */
uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */
uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */
+
+ /* Min/max LOD must be clamped to [0, last_level], thus
+ * it's dependent on a currently bound texture */
+ unsigned min_lod, max_lod;
};
struct r300_scissor_state {
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 6d702c00272..ad7dff36bea 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -583,6 +583,8 @@ void r300_emit_texture(struct r300_context* r300,
unsigned offset)
{
uint32_t filter0 = sampler->filter0;
+ uint32_t format0 = tex->state.format0;
+ unsigned min_level, max_level;
CS_LOCALS(r300);
/* to emulate 1D textures through 2D ones correctly */
@@ -591,13 +593,20 @@ void r300_emit_texture(struct r300_context* r300,
filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE);
}
+ /* determine min/max levels */
+ /* the MAX_MIP level is the largest (finest) one */
+ max_level = MIN2(sampler->max_lod, tex->tex.last_level);
+ min_level = MIN2(sampler->min_lod, max_level);
+ format0 |= R300_TX_NUM_LEVELS(max_level);
+ filter0 |= R300_TX_MAX_MIP_LEVEL(min_level);
+
BEGIN_CS(16);
OUT_CS_REG(R300_TX_FILTER0_0 + (offset * 4), filter0 |
(offset << 28));
OUT_CS_REG(R300_TX_FILTER1_0 + (offset * 4), sampler->filter1);
OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (offset * 4), sampler->border_color);
- OUT_CS_REG(R300_TX_FORMAT0_0 + (offset * 4), tex->state.format0);
+ OUT_CS_REG(R300_TX_FORMAT0_0 + (offset * 4), format0);
OUT_CS_REG(R300_TX_FORMAT1_0 + (offset * 4), tex->state.format1);
OUT_CS_REG(R300_TX_FORMAT2_0 + (offset * 4), tex->state.format2);
OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (offset * 4), 1);
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index 8ca785cb587..66fdada2210 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -1463,6 +1463,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_TX_MIN_FILTER_MIP_NEAREST (1 << 13)
# define R300_TX_MIN_FILTER_MIP_LINEAR (2 << 13)
# define R300_TX_MIN_FILTER_MIP_MASK (3 << 13)
+# define R300_TX_MAX_MIP_LEVEL_SHIFT 17
+# define R300_TX_MAX_MIP_LEVEL_MASK (0xf << 17)
# define R300_TX_MAX_ANISO_1_TO_1 (0 << 21)
# define R300_TX_MAX_ANISO_2_TO_1 (1 << 21)
# define R300_TX_MAX_ANISO_4_TO_1 (2 << 21)
@@ -1471,6 +1473,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_TX_MAX_ANISO_MASK (7 << 21)
# define R300_TX_WRAP_S(x) ((x) << 0)
# define R300_TX_WRAP_T(x) ((x) << 3)
+# define R300_TX_MAX_MIP_LEVEL(x) ((x) << 17)
#define R300_TX_FILTER1_0 0x4440
# define R300_CHROMA_KEY_MODE_DISABLE 0
@@ -1500,8 +1503,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_TX_HEIGHTMASK_MASK (2047 << 11)
# define R300_TX_DEPTHMASK_SHIFT 22
# define R300_TX_DEPTHMASK_MASK (0xf << 22)
-# define R300_TX_MAX_MIP_LEVEL_SHIFT 26
-# define R300_TX_MAX_MIP_LEVEL_MASK (0xf << 26)
# define R300_TX_SIZE_PROJECTED (1 << 30)
# define R300_TX_PITCH_EN (1 << 31)
# define R300_TX_WIDTH(x) ((x) << 0)
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index 5422a2cc9c8..f2867675f0f 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -523,6 +523,11 @@ static void*
state->mag_img_filter,
state->min_mip_filter);
+ /* Unfortunately, r300-r500 don't support floating-point mipmap lods. */
+ /* We must pass these to the emit function to clamp them properly. */
+ sampler->min_lod = MAX2((unsigned)state->min_lod, 0);
+ sampler->max_lod = MAX2((unsigned)ceilf(state->max_lod), 0);
+
lod_bias = CLAMP((int)(state->lod_bias * 32), -(1 << 9), (1 << 9) - 1);
sampler->filter1 |= lod_bias << R300_LOD_BIAS_SHIFT;
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index aea25cf71dd..d13aa8f036b 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -43,8 +43,7 @@ static void r300_setup_texture_state(struct r300_texture* tex, boolean is_r500)
state->format2 = (tex->pitch[0] - 1) & 0x1fff;
} else {
/* power of two textures (3D, mipmaps, and no pitch) */
- state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth[0]) & 0xf) |
- R300_TX_NUM_LEVELS(pt->last_level & 0xf);
+ state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth[0]) & 0xf);
}
state->format1 = r300_translate_texformat(pt->format);