From c5b8ba9368fe935af9f350874f3c03f5a230d4b5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sat, 28 Aug 2010 07:54:36 +0200 Subject: [PATCH] r300g: fix blitting between 2D NPOT mipmaps Even though MIP filtering is not supported, we can bind an arbitrary mipmap as the zero mipmap level. NPOT textures now follow GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MIN_LOD. This fixes piglit/fbo-copyteximage. --- src/gallium/drivers/r300/r300_reg.h | 1 + src/gallium/drivers/r300/r300_state_derived.c | 24 ++++++++--- src/gallium/drivers/r300/r300_texture.c | 43 +++++++++++-------- src/gallium/drivers/r300/r300_texture.h | 6 +++ 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index 60d3b600cb7..6bea783f697 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -1607,6 +1607,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TX_FORMAT_3D (1 << 25) # define R300_TX_FORMAT_CUBIC_MAP (2 << 25) +# define R300_TX_FORMAT_TEX_COORD_TYPE_MASK (0x3 << 25) /* alpha modes, convenience mostly */ /* if you have alpha, pick constant appropriate to the diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index c8de3e1c523..960dfdbaf03 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -592,6 +592,25 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->filter1 = sampler->filter1; texstate->border_color = sampler->border_color; + /* determine min/max levels */ + max_level = MIN3(sampler->max_lod + view->base.first_level, + tex->desc.b.b.last_level, view->base.last_level); + min_level = MIN2(sampler->min_lod + view->base.first_level, + max_level); + + if (tex->desc.is_npot && min_level > 0) { + /* Even though we do not implement mipmapping for NPOT + * textures, we should at least honor the minimum level + * which is allowed to be displayed. We do this by setting up + * an i-th mipmap level as the zero level. */ + r300_texture_setup_format_state(r300->screen, &tex->desc, + min_level, + &texstate->format); + texstate->format.tile_config |= + tex->desc.offset_in_bytes[min_level] & 0xffffffe0; + assert((tex->desc.offset_in_bytes[min_level] & 0x1f) == 0); + } + /* Assign a texture cache region. */ texstate->format.format1 |= view->texcache_region; @@ -654,12 +673,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); } } else { - /* determine min/max levels */ /* the MAX_MIP level is the largest (finest) one */ - max_level = MIN3(sampler->max_lod + view->base.first_level, - tex->desc.b.b.last_level, view->base.last_level); - min_level = MIN2(sampler->min_lod + view->base.first_level, - max_level); texstate->format.format0 |= R300_TX_NUM_LEVELS(max_level); texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 852acdd4620..66f6d80bd0c 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -541,48 +541,55 @@ boolean r300_is_sampler_format_supported(enum pipe_format format) return r300_translate_texformat(format, 0, TRUE) != ~0; } -static void r300_texture_setup_immutable_state(struct r300_screen* screen, - struct r300_texture* tex) +void r300_texture_setup_format_state(struct r300_screen *screen, + struct r300_texture_desc *desc, + unsigned level, + struct r300_texture_format_state *out) { - struct r300_texture_format_state* f = &tex->tx_format; - struct pipe_resource *pt = &tex->desc.b.b; + struct pipe_resource *pt = &desc->b.b; boolean is_r500 = screen->caps.is_r500; + /* Mask out all the fields we change. */ + out->format0 = 0; + out->format1 &= ~R300_TX_FORMAT_TEX_COORD_TYPE_MASK; + out->format2 &= R500_TXFORMAT_MSB; + out->tile_config = 0; + /* Set sampler state. */ - f->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | - R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); + out->format0 = R300_TX_WIDTH((u_minify(pt->width0, level) - 1) & 0x7ff) | + R300_TX_HEIGHT((u_minify(pt->height0, level) - 1) & 0x7ff); - if (tex->desc.uses_stride_addressing) { + if (desc->uses_stride_addressing) { /* rectangles love this */ - f->format0 |= R300_TX_PITCH_EN; - f->format2 = (tex->desc.stride_in_pixels[0] - 1) & 0x1fff; + 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. */ - f->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf); + out->format0 |= + R300_TX_DEPTH(util_logbase2(u_minify(pt->depth0, level)) & 0xf); } - f->format1 = 0; if (pt->target == PIPE_TEXTURE_CUBE) { - f->format1 |= R300_TX_FORMAT_CUBIC_MAP; + out->format1 |= R300_TX_FORMAT_CUBIC_MAP; } if (pt->target == PIPE_TEXTURE_3D) { - f->format1 |= R300_TX_FORMAT_3D; + out->format1 |= R300_TX_FORMAT_3D; } /* large textures on r500 */ if (is_r500) { if (pt->width0 > 2048) { - f->format2 |= R500_TXWIDTH_BIT11; + out->format2 |= R500_TXWIDTH_BIT11; } if (pt->height0 > 2048) { - f->format2 |= R500_TXHEIGHT_BIT11; + out->format2 |= R500_TXHEIGHT_BIT11; } } - f->tile_config = R300_TXO_MACRO_TILE(tex->desc.macrotile[0]) | - R300_TXO_MICRO_TILE(tex->desc.microtile); + out->tile_config = R300_TXO_MACRO_TILE(desc->macrotile[level]) | + R300_TXO_MICRO_TILE(desc->microtile); } static void r300_texture_setup_fb_state(struct r300_screen* screen, @@ -716,7 +723,7 @@ r300_texture_create_object(struct r300_screen *rscreen, return NULL; } /* Initialize the hardware state. */ - r300_texture_setup_immutable_state(rscreen, tex); + r300_texture_setup_format_state(rscreen, &tex->desc, 0, &tex->tx_format); r300_texture_setup_fb_state(rscreen, tex); tex->desc.b.vtbl = &r300_texture_vtbl; diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 5a371a54a84..c4588a0c90b 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -29,6 +29,8 @@ struct pipe_screen; struct pipe_resource; struct winsys_handle; +struct r300_texture_format_state; +struct r300_texture_desc; struct r300_texture; struct r300_screen; @@ -51,6 +53,10 @@ boolean r300_is_zs_format_supported(enum pipe_format format); boolean r300_is_sampler_format_supported(enum pipe_format format); +void r300_texture_setup_format_state(struct r300_screen *screen, + struct r300_texture_desc *desc, + unsigned level, + struct r300_texture_format_state *out); struct pipe_resource* r300_texture_from_handle(struct pipe_screen* screen, -- 2.30.2