diff options
-rw-r--r-- | src/gallium/drivers/r300/r300_context.h | 7 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.c | 16 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_fs.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture_desc.c | 35 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_code.h | 9 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c | 32 |
7 files changed, 90 insertions, 27 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 1927370325e..b59bc002610 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -336,6 +336,13 @@ struct r300_texture_desc { /* Parent class. */ struct u_resource b; + /* Width, height, and depth. + * Most of the time, these are equal to pipe_texture::width0, height0, + * and depth0. However, NPOT 3D textures must have dimensions aligned + * to POT, and this is the only case when these variables differ from + * pipe_texture. */ + unsigned width0, height0, depth0; + /* Buffer tiling. * Macrotiling is specified per-level because small mipmaps cannot * be macrotiled. */ diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index db783ff0add..3a1085d2dc5 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -89,7 +89,7 @@ static const float * get_rc_constant_state( { struct r300_textures_state* texstate = r300->textures_state.state; static float vec[4] = { 0.0, 0.0, 0.0, 1.0 }; - struct pipe_resource *tex; + struct r300_texture *tex; assert(constant->Type == RC_CONSTANT_STATE); @@ -97,9 +97,17 @@ static const float * get_rc_constant_state( /* Factor for converting rectangle coords to * normalized coords. Should only show up on non-r500. */ case RC_STATE_R300_TEXRECT_FACTOR: - tex = texstate->sampler_views[constant->u.State[1]]->base.texture; - vec[0] = 1.0 / tex->width0; - vec[1] = 1.0 / tex->height0; + tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture); + vec[0] = 1.0 / tex->desc.width0; + vec[1] = 1.0 / tex->desc.height0; + break; + + case RC_STATE_R300_TEXSCALE_FACTOR: + tex = r300_texture(texstate->sampler_views[constant->u.State[1]]->base.texture); + /* Add a small number to the texture size to work around rounding errors in hw. */ + vec[0] = tex->desc.b.b.width0 / (tex->desc.width0 + 0.001f); + vec[1] = tex->desc.b.b.height0 / (tex->desc.height0 + 0.001f); + vec[2] = tex->desc.b.b.depth0 / (tex->desc.depth0 + 0.001f); break; case RC_STATE_R300_VIEWPORT_SCALE: diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 3f89987897d..d9d4a9304df 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -200,6 +200,9 @@ static void get_external_state( default: state->unit[i].wrap_mode = RC_WRAP_NONE; } + + if (t->desc.b.b.target == PIPE_TEXTURE_3D) + state->unit[i].clamp_and_scale_before_fetch = TRUE; } } } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 34105aa4bcd..a7911c6fcc4 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -556,18 +556,15 @@ void r300_texture_setup_format_state(struct r300_screen *screen, out->tile_config = 0; /* Set sampler state. */ - out->format0 = R300_TX_WIDTH((u_minify(pt->width0, level) - 1) & 0x7ff) | - R300_TX_HEIGHT((u_minify(pt->height0, level) - 1) & 0x7ff); + out->format0 = + R300_TX_WIDTH((u_minify(desc->width0, level) - 1) & 0x7ff) | + R300_TX_HEIGHT((u_minify(desc->height0, level) - 1) & 0x7ff) | + R300_TX_DEPTH(util_logbase2(u_minify(desc->depth0, level)) & 0xf); if (desc->uses_stride_addressing) { /* rectangles love this */ out->format0 |= R300_TX_PITCH_EN; out->format2 = (desc->stride_in_pixels[level] - 1) & 0x1fff; - } else { - /* Power of two textures (3D, mipmaps, and no pitch), - * also NPOT textures with a width being POT. */ - out->format0 |= - R300_TX_DEPTH(util_logbase2(u_minify(pt->depth0, level)) & 0xf); } if (pt->target == PIPE_TEXTURE_CUBE) { @@ -580,10 +577,10 @@ void r300_texture_setup_format_state(struct r300_screen *screen, /* large textures on r500 */ if (is_r500) { - if (pt->width0 > 2048) { + if (desc->width0 > 2048) { out->format2 |= R500_TXWIDTH_BIT11; } - if (pt->height0 > 2048) { + if (desc->height0 > 2048) { out->format2 |= R500_TXHEIGHT_BIT11; } } diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c index 6a1030f8eee..a49029e1e92 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.c +++ b/src/gallium/drivers/r300/r300_texture_desc.c @@ -91,9 +91,9 @@ static boolean r300_texture_macro_switch(struct r300_texture_desc *desc, tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples, desc->microtile, R300_BUFFER_TILED, dim); if (dim == DIM_WIDTH) { - texdim = u_minify(desc->b.b.width0, level); + texdim = u_minify(desc->width0, level); } else { - texdim = u_minify(desc->b.b.height0, level); + texdim = u_minify(desc->height0, level); } /* See TX_FILTER1_n.MACRO_SWITCH. */ @@ -124,7 +124,7 @@ static unsigned r300_texture_get_stride(struct r300_screen *screen, return 0; } - width = u_minify(desc->b.b.width0, level); + width = u_minify(desc->width0, level); if (util_format_is_plain(desc->b.b.format)) { tile_width = r300_get_pixel_alignment(desc->b.b.format, @@ -172,7 +172,7 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, { unsigned height, tile_height; - height = u_minify(desc->b.b.height0, level); + height = u_minify(desc->height0, level); if (util_format_is_plain(desc->b.b.format)) { tile_height = r300_get_pixel_alignment(desc->b.b.format, @@ -237,7 +237,7 @@ static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, r300_texture_get_nblocksy(desc, i, FALSE); } - size *= desc->b.b.depth0; + size *= desc->depth0; desc->size_in_bytes = size; } } @@ -292,7 +292,7 @@ static void r300_setup_miptree(struct r300_screen *screen, if (base->target == PIPE_TEXTURE_CUBE) size = layer_size * 6; else - size = layer_size * u_minify(base->depth0, i); + size = layer_size * u_minify(desc->depth0, i); desc->offset_in_bytes[i] = desc->size_in_bytes; desc->size_in_bytes = desc->offset_in_bytes[i] + size; @@ -303,8 +303,8 @@ static void r300_setup_miptree(struct r300_screen *screen, SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d " "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n", - i, u_minify(base->width0, i), u_minify(base->height0, i), - u_minify(base->depth0, i), stride, desc->size_in_bytes, + i, u_minify(desc->width0, i), u_minify(desc->height0, i), + u_minify(desc->depth0, i), stride, desc->size_in_bytes, desc->macrotile[i] ? "TRUE" : "FALSE"); } } @@ -313,14 +313,14 @@ static void r300_setup_flags(struct r300_texture_desc *desc) { desc->uses_stride_addressing = !util_is_power_of_two(desc->b.b.width0) || - !util_is_power_of_two(desc->b.b.height0) || (desc->stride_in_bytes_override && stride_to_width(desc->b.b.format, desc->stride_in_bytes_override) != desc->b.b.width0); desc->is_npot = desc->uses_stride_addressing || - !util_is_power_of_two(desc->b.b.height0); + !util_is_power_of_two(desc->b.b.height0) || + !util_is_power_of_two(desc->b.b.depth0); } static void r300_setup_cbzb_flags(struct r300_screen *rscreen, @@ -416,9 +416,21 @@ boolean r300_texture_desc_init(struct r300_screen *rscreen, { desc->b.b = *base; desc->b.b.screen = &rscreen->screen; - desc->stride_in_bytes_override = stride_in_bytes_override; + desc->width0 = base->width0; + desc->height0 = base->height0; + desc->depth0 = base->depth0; + + r300_setup_flags(desc); + + /* Align a 3D NPOT texture to POT. */ + if (base->target == PIPE_TEXTURE_3D && desc->is_npot) { + desc->width0 = util_next_power_of_two(desc->width0); + desc->height0 = util_next_power_of_two(desc->height0); + desc->depth0 = util_next_power_of_two(desc->depth0); + } + /* Setup tiling. */ if (microtile == R300_BUFFER_SELECT_LAYOUT || macrotile == R300_BUFFER_SELECT_LAYOUT) { r300_setup_tiling(rscreen, desc); @@ -428,7 +440,6 @@ boolean r300_texture_desc_init(struct r300_screen *rscreen, assert(desc->b.b.last_level == 0); } - r300_setup_flags(desc); r300_setup_cbzb_flags(rscreen, desc); /* Setup the miptree description. */ diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_code.h b/src/mesa/drivers/dri/r300/compiler/radeon_code.h index 53cc1bd77e9..2dd9c5e4bd3 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_code.h +++ b/src/mesa/drivers/dri/r300/compiler/radeon_code.h @@ -60,6 +60,7 @@ enum { RC_STATE_R300_WINDOW_DIMENSION, RC_STATE_R300_TEXRECT_FACTOR, + RC_STATE_R300_TEXSCALE_FACTOR, RC_STATE_R300_VIEWPORT_SCALE, RC_STATE_R300_VIEWPORT_OFFSET }; @@ -158,7 +159,13 @@ struct r300_fragment_program_external_state { * If this field is \ref RC_WRAP_NONE (aka 0), no wrapping maths * will be performed on the coordinates. */ - unsigned wrap_mode : 2; + unsigned wrap_mode : 3; + + /** + * The coords are scaled after applying the wrap mode emulation + * and right before texture fetch. The scaling factor is given by + * RC_STATE_R300_TEXSCALE_FACTOR. */ + unsigned clamp_and_scale_before_fetch : 1; } unit[16]; }; diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c index de988b7c10c..530afa5e08e 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_tex.c @@ -252,7 +252,8 @@ int radeonTransformTEX( /* Divide by W if needed. */ if (inst->U.I.Opcode == RC_OPCODE_TXP && - (wrapmode == RC_WRAP_REPEAT || wrapmode == RC_WRAP_MIRRORED_REPEAT)) { + (wrapmode == RC_WRAP_REPEAT || wrapmode == RC_WRAP_MIRRORED_REPEAT || + compiler->state.unit[inst->U.I.TexSrcUnit].clamp_and_scale_before_fetch)) { projective_divide(compiler, inst); } @@ -388,6 +389,35 @@ int radeonTransformTEX( inst->U.I.SrcReg[0].Index = temp; } + if (inst->U.I.Opcode != RC_OPCODE_KIL && + compiler->state.unit[inst->U.I.TexSrcUnit].clamp_and_scale_before_fetch) { + struct rc_instruction *inst_mov; + unsigned temp = rc_find_free_temporary(c); + + /* Saturate XYZ. */ + inst_mov = rc_insert_new_instruction(c, inst->Prev); + inst_mov->U.I.Opcode = RC_OPCODE_MOV; + inst_mov->U.I.SaturateMode = RC_SATURATE_ZERO_ONE; + inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_mov->U.I.DstReg.Index = temp; + inst_mov->U.I.DstReg.WriteMask = RC_MASK_XYZ; + inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; + + /* Copy W. */ + inst_mov = rc_insert_new_instruction(c, inst->Prev); + inst_mov->U.I.Opcode = RC_OPCODE_MOV; + inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY; + inst_mov->U.I.DstReg.Index = temp; + inst_mov->U.I.DstReg.WriteMask = RC_MASK_W; + inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0]; + + reset_srcreg(&inst->U.I.SrcReg[0]); + inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY; + inst->U.I.SrcReg[0].Index = temp; + + scale_texcoords(compiler, inst, RC_STATE_R300_TEXSCALE_FACTOR); + } + /* Cannot write texture to output registers (all chips) or with masks (non-r500) */ if (inst->U.I.Opcode != RC_OPCODE_KIL && (inst->U.I.DstReg.File != RC_FILE_TEMPORARY || |