From: Marek Olšák Date: Thu, 29 Dec 2011 17:18:38 +0000 (+0100) Subject: r300g: rework resource_copy_region, not changing pipe_resource X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ce9d61fec64138ebf8d0bec2511e66593297b7d5;p=mesa.git r300g: rework resource_copy_region, not changing pipe_resource Changing pipe_resource was wrong, because it can be used by other contexts at the same time. This fixes the last possible race condition in r300g that I know of. This also fixes blitting NPOT compressed textures. Random pixels sometimes appeared at the right-hand edge of the texture. Finally, this removes r300_texture_desc::stride_in_pixels. It makes little sense with sampler views and surfaces being able to override width0, height0, and the format entirely. --- diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 3974aea878f..c780c8dd1ad 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -434,21 +434,14 @@ void r300_decompress_zmask_locked(struct r300_context *r300) pipe_surface_reference(&r300->locked_zbuffer, NULL); } -/* Copy a block of pixels from one surface to another using HW. */ -static void r300_hw_copy_region(struct pipe_context* pipe, - struct pipe_resource *dst, - unsigned dst_level, - unsigned dstx, unsigned dsty, unsigned dstz, - struct pipe_resource *src, - unsigned src_level, - const struct pipe_box *src_box) +bool r300_is_blit_supported(enum pipe_format format) { - struct r300_context* r300 = r300_context(pipe); + const struct util_format_description *desc = + util_format_description(format); - r300_blitter_begin(r300, R300_COPY); - util_blitter_copy_texture(r300->blitter, dst, dst_level, dstx, dsty, dstz, - src, src_level, src_box, TRUE); - r300_blitter_end(r300); + return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN || + desc->layout == UTIL_FORMAT_LAYOUT_S3TC || + desc->layout == UTIL_FORMAT_LAYOUT_RGTC; } /* Copy a block of pixels from one surface to another. */ @@ -460,103 +453,138 @@ static void r300_resource_copy_region(struct pipe_context *pipe, unsigned src_level, const struct pipe_box *src_box) { + struct pipe_screen *screen = pipe->screen; struct r300_context *r300 = r300_context(pipe); struct pipe_framebuffer_state *fb = (struct pipe_framebuffer_state*)r300->fb_state.state; - struct pipe_resource old_src = *src; - struct pipe_resource old_dst = *dst; - struct pipe_resource new_src = old_src; - struct pipe_resource new_dst = old_dst; - const struct util_format_description *desc = - util_format_description(dst->format); + unsigned src_width0 = r300_resource(src)->tex.width0; + unsigned src_height0 = r300_resource(src)->tex.height0; + unsigned dst_width0 = r300_resource(dst)->tex.width0; + unsigned dst_height0 = r300_resource(dst)->tex.height0; + unsigned layout; struct pipe_box box; + struct pipe_sampler_view src_templ, *src_view; + struct pipe_surface dst_templ, *dst_view; /* Fallback for buffers. */ - if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { + if ((dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) || + !r300_is_blit_supported(dst->format)) { util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); return; } - if (r300->zmask_in_use && !r300->locked_zbuffer) { - if (fb->zsbuf->texture == src || - fb->zsbuf->texture == dst) { - r300_decompress_zmask(r300); - } - } + /* The code below changes the texture format so that the copy can be done + * on hardware. E.g. depth-stencil surfaces are copied as RGBA + * colorbuffers. */ + + util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz, src_box); + util_blitter_default_src_texture(&src_templ, src, src_level); + + layout = util_format_description(dst_templ.format)->layout; /* Handle non-renderable plain formats. */ - if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && - (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB || - !pipe->screen->is_format_supported(pipe->screen, - src->format, src->target, - src->nr_samples, - PIPE_BIND_SAMPLER_VIEW) || - !pipe->screen->is_format_supported(pipe->screen, - dst->format, dst->target, - dst->nr_samples, - PIPE_BIND_RENDER_TARGET))) { - switch (util_format_get_blocksize(old_dst.format)) { + if (layout == UTIL_FORMAT_LAYOUT_PLAIN && + (!screen->is_format_supported(screen, src_templ.format, src->target, + src->nr_samples, + PIPE_BIND_SAMPLER_VIEW) || + !screen->is_format_supported(screen, dst_templ.format, dst->target, + dst->nr_samples, + PIPE_BIND_RENDER_TARGET))) { + switch (util_format_get_blocksize(dst_templ.format)) { case 1: - new_dst.format = PIPE_FORMAT_I8_UNORM; + dst_templ.format = PIPE_FORMAT_I8_UNORM; break; case 2: - new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM; + dst_templ.format = PIPE_FORMAT_B4G4R4A4_UNORM; break; case 4: - new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM; + dst_templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; break; case 8: - new_dst.format = PIPE_FORMAT_R16G16B16A16_UNORM; + dst_templ.format = PIPE_FORMAT_R16G16B16A16_UNORM; break; default: - debug_printf("r300: surface_copy: Unhandled format: %s. Falling back to software.\n" - "r300: surface_copy: Software fallback doesn't work for tiled textures.\n", - util_format_short_name(dst->format)); + debug_printf("r300: copy_region: Unhandled format: %s. Falling back to software.\n" + "r300: copy_region: Software fallback doesn't work for tiled textures.\n", + util_format_short_name(dst_templ.format)); } - new_src.format = new_dst.format; + src_templ.format = dst_templ.format; } /* Handle compressed formats. */ - if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC || - desc->layout == UTIL_FORMAT_LAYOUT_RGTC) { - switch (util_format_get_blocksize(old_dst.format)) { + if (layout == UTIL_FORMAT_LAYOUT_S3TC || + layout == UTIL_FORMAT_LAYOUT_RGTC) { + assert(src_templ.format == dst_templ.format); + + box = *src_box; + src_box = &box; + + dst_width0 = align(dst_width0, 4); + dst_height0 = align(dst_height0, 4); + src_width0 = align(src_width0, 4); + src_height0 = align(src_height0, 4); + box.width = align(box.width, 4); + box.height = align(box.height, 4); + + switch (util_format_get_blocksize(dst_templ.format)) { case 8: - /* 1 pixel = 4 bits, - * we set 1 pixel = 2 bytes ===> 4 times larger pixels. */ - new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM; + /* one 4x4 pixel block has 8 bytes. + * we set 1 pixel = 4 bytes ===> 1 block corrensponds to 2 pixels. */ + dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; + dst_width0 = dst_width0 / 2; + src_width0 = src_width0 / 2; + dstx /= 2; + box.x /= 2; + box.width /= 2; break; case 16: - /* 1 pixel = 8 bits, - * we set 1 pixel = 4 bytes ===> 4 times larger pixels. */ - new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM; + /* one 4x4 pixel block has 16 bytes. + * we set 1 pixel = 4 bytes ===> 1 block corresponds to 4 pixels. */ + dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; break; } + src_templ.format = dst_templ.format; - /* Since the pixels are 4 times larger, we must decrease - * the image size and the coordinates 4 times. */ - new_src.format = new_dst.format; - new_dst.height0 = (new_dst.height0 + 3) / 4; - new_src.height0 = (new_src.height0 + 3) / 4; + dst_height0 = dst_height0 / 4; + src_height0 = src_height0 / 4; dsty /= 4; - box = *src_box; box.y /= 4; - box.height = (box.height + 3) / 4; - src_box = &box; + box.height /= 4; } - if (old_src.format != new_src.format) - r300_resource_set_properties(pipe->screen, src, &new_src); - if (old_dst.format != new_dst.format) - r300_resource_set_properties(pipe->screen, dst, &new_dst); + /* Fallback for textures. */ + if (!screen->is_format_supported(screen, dst_templ.format, + dst->target, dst->nr_samples, + PIPE_BIND_RENDER_TARGET) || + !screen->is_format_supported(screen, src_templ.format, + src->target, src->nr_samples, + PIPE_BIND_SAMPLER_VIEW)) { + assert(0 && "this shouldn't happen, update r300_is_blit_supported"); + util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box); + return; + } - r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, - src, src_level, src_box); + /* Decompress ZMASK. */ + if (r300->zmask_in_use && !r300->locked_zbuffer) { + if (fb->zsbuf->texture == src || + fb->zsbuf->texture == dst) { + r300_decompress_zmask(r300); + } + } + + dst_view = r300_create_surface_custom(pipe, dst, &dst_templ, dst_width0, dst_height0); + src_view = r300_create_sampler_view_custom(pipe, src, &src_templ, src_width0, src_height0); + + r300_blitter_begin(r300, R300_COPY); + util_blitter_copy_texture_view(r300->blitter, dst_view, dstx, dsty, + src_view, src_box, + src_width0, src_height0); + r300_blitter_end(r300); - if (old_src.format != new_src.format) - r300_resource_set_properties(pipe->screen, src, &old_src); - if (old_dst.format != new_dst.format) - r300_resource_set_properties(pipe->screen, dst, &old_dst); + pipe_surface_reference(&dst_view, NULL); + pipe_sampler_view_reference(&src_view, NULL); } void r300_init_blit_functions(struct r300_context *r300) diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 5c0f53e9aad..5588e51ada9 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -196,6 +196,10 @@ struct r300_texture_format_state { struct r300_sampler_view { struct pipe_sampler_view base; + /* For resource_copy_region. */ + unsigned width0_override; + unsigned height0_override; + /* Swizzles in the UTIL_FORMAT_SWIZZLE_* representation, * derived from base. */ unsigned char swizzle[4]; @@ -339,7 +343,6 @@ struct r300_texture_desc { unsigned offset_in_bytes[R300_MAX_TEXTURE_LEVELS]; /* Strides for each mip-level. */ - unsigned stride_in_pixels[R300_MAX_TEXTURE_LEVELS]; unsigned stride_in_bytes[R300_MAX_TEXTURE_LEVELS]; /* Size of one zslice or face or 2D image based on the texture target. */ @@ -395,10 +398,6 @@ struct r300_resource /* Texture description (addressing, layout, special features). */ struct r300_texture_desc tex; - /* Registers carrying texture format data. */ - /* Only format-independent bits should be filled in. */ - struct r300_texture_format_state tx_format; - /* This is the level tiling flags were last time set for. * It's used to prevent redundant tiling-flags changes from happening.*/ unsigned surface_level; @@ -680,6 +679,7 @@ void r300_init_resource_functions(struct r300_context* r300); void r300_decompress_zmask(struct r300_context *r300); void r300_decompress_zmask_locked_unsafe(struct r300_context *r300); void r300_decompress_zmask_locked(struct r300_context *r300); +bool r300_is_blit_supported(enum pipe_format format); /* r300_flush.c */ void r300_flush(struct pipe_context *pipe, @@ -718,6 +718,13 @@ void r300_mark_fb_state_dirty(struct r300_context *r300, enum r300_fb_state_change change); void r300_mark_fs_code_dirty(struct r300_context *r300); +struct pipe_sampler_view * +r300_create_sampler_view_custom(struct pipe_context *pipe, + struct pipe_resource *texture, + const struct pipe_sampler_view *templ, + unsigned width0_override, + unsigned height0_override); + /* r300_state_derived.c */ void r300_update_derived_state(struct r300_context* r300); diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index d704057e466..3606e0bf505 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -756,7 +756,7 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, "r300: %s[%i] Dim: %ix%i, Firstlayer: %i, " "Lastlayer: %i, Level: %i, Format: %s\n" - "r300: TEX: Macro: %s, Micro: %s, Pitch: %i, " + "r300: TEX: Macro: %s, Micro: %s, " "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n", binding, index, surf->width, surf->height, @@ -765,9 +765,8 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, rtex->tex.macrotile[0] ? "YES" : " NO", rtex->tex.microtile ? "YES" : " NO", - rtex->tex.stride_in_pixels[0], tex->width0, tex->height0, tex->depth0, - tex->last_level, util_format_short_name(tex->format)); + tex->last_level, util_format_short_name(surf->format)); } void r300_mark_fb_state_dirty(struct r300_context *r300, @@ -888,7 +887,7 @@ r300_set_framebuffer_state(struct pipe_context* pipe, r300_mark_fb_state_dirty(r300, R300_CHANGED_FB_STATE); if (state->zsbuf) { - switch (util_format_get_blocksize(state->zsbuf->texture->format)) { + switch (util_format_get_blocksize(state->zsbuf->format)) { case 2: zbuffer_bpp = 16; break; @@ -1458,10 +1457,12 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, } } -static struct pipe_sampler_view * -r300_create_sampler_view(struct pipe_context *pipe, +struct pipe_sampler_view * +r300_create_sampler_view_custom(struct pipe_context *pipe, struct pipe_resource *texture, - const struct pipe_sampler_view *templ) + const struct pipe_sampler_view *templ, + unsigned width0_override, + unsigned height0_override) { struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view); struct r300_resource *tex = r300_resource(texture); @@ -1477,6 +1478,8 @@ r300_create_sampler_view(struct pipe_context *pipe, view->base.texture = NULL; pipe_resource_reference(&view->base.texture, texture); + view->width0_override = width0_override; + view->height0_override = height0_override; view->swizzle[0] = templ->swizzle_r; view->swizzle[1] = templ->swizzle_g; view->swizzle[2] = templ->swizzle_b; @@ -1493,7 +1496,10 @@ r300_create_sampler_view(struct pipe_context *pipe, } assert(hwformat != ~0); - view->format = tex->tx_format; + r300_texture_setup_format_state(r300_screen(pipe->screen), tex, + templ->format, 0, + width0_override, height0_override, + &view->format); view->format.format1 |= hwformat; if (is_r500) { view->format.format2 |= r500_tx_format_msb_bit(templ->format); @@ -1503,6 +1509,17 @@ r300_create_sampler_view(struct pipe_context *pipe, return (struct pipe_sampler_view*)view; } +static struct pipe_sampler_view * +r300_create_sampler_view(struct pipe_context *pipe, + struct pipe_resource *texture, + const struct pipe_sampler_view *templ) +{ + return r300_create_sampler_view_custom(pipe, texture, templ, + r300_resource(texture)->tex.width0, + r300_resource(texture)->tex.height0); +} + + static void r300_sampler_view_destroy(struct pipe_context *pipe, struct pipe_sampler_view *view) diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index c1e25c63ba6..2dabf18d5e8 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -785,7 +785,10 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) offset = tex->tex.offset_in_bytes[base_level]; r300_texture_setup_format_state(r300->screen, tex, + view->base.format, base_level, + view->width0_override, + view->height0_override, &texstate->format); texstate->format.tile_config |= offset & 0xffffffe0; assert((offset & 0x1f) == 0); @@ -795,11 +798,11 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->format.format1 |= view->texcache_region; /* Depth textures are kinda special. */ - if (util_format_is_depth_or_stencil(tex->b.b.b.format)) { + if (util_format_is_depth_or_stencil(view->base.format)) { unsigned char depth_swizzle[4]; if (!r300->screen->caps.is_r500 && - util_format_get_blocksizebits(tex->b.b.b.format) == 32) { + util_format_get_blocksizebits(view->base.format) == 32) { /* X24x8 is sampled as Y16X16 on r3xx-r4xx. * The depth here is at the Y component. */ for (j = 0; j < 4; j++) @@ -824,7 +827,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } if (r300->screen->caps.dxtc_swizzle && - util_format_is_compressed(tex->b.b.b.format)) { + util_format_is_compressed(view->base.format)) { texstate->filter1 |= R400_DXTC_SWIZZLE_ENABLE; } @@ -870,7 +873,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } /* Float textures only support nearest and mip-nearest filtering. */ - if (util_format_is_float(tex->b.b.b.format)) { + if (util_format_is_float(view->base.format)) { /* No MAG linear filtering. */ if ((texstate->filter0 & R300_TX_MAG_FILTER_MASK) == R300_TX_MAG_FILTER_LINEAR) { diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 6fc60fb60d6..b63afa18c2b 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -722,7 +722,10 @@ boolean r300_is_sampler_format_supported(enum pipe_format format) void r300_texture_setup_format_state(struct r300_screen *screen, struct r300_resource *tex, + enum pipe_format format, unsigned level, + unsigned width0_override, + unsigned height0_override, struct r300_texture_format_state *out) { struct pipe_resource *pt = &tex->b.b.b; @@ -731,8 +734,8 @@ void r300_texture_setup_format_state(struct r300_screen *screen, unsigned width, height, depth; unsigned txwidth, txheight, txdepth; - width = u_minify(desc->width0, level); - height = u_minify(desc->height0, level); + width = u_minify(width0_override, level); + height = u_minify(height0_override, level); depth = u_minify(desc->depth0, level); txwidth = (width - 1) & 0x7ff; @@ -752,9 +755,11 @@ void r300_texture_setup_format_state(struct r300_screen *screen, R300_TX_DEPTH(txdepth); if (desc->uses_stride_addressing) { + unsigned stride = + r300_stride_to_width(format, desc->stride_in_bytes[level]); /* rectangles love this */ out->format0 |= R300_TX_PITCH_EN; - out->format2 = (desc->stride_in_pixels[level] - 1) & 0x1fff; + out->format2 = (stride - 1) & 0x1fff; } if (pt->target == PIPE_TEXTURE_CUBE) { @@ -803,11 +808,13 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf) { struct r300_resource *tex = r300_resource(surf->base.texture); unsigned level = surf->base.u.tex.level; + unsigned stride = + r300_stride_to_width(surf->base.format, tex->tex.stride_in_bytes[level]); /* Set framebuffer state. */ if (util_format_is_depth_or_stencil(surf->base.format)) { surf->pitch = - tex->tex.stride_in_pixels[level] | + stride | R300_DEPTHMACROTILE(tex->tex.macrotile[level]) | R300_DEPTHMICROTILE(tex->tex.microtile); surf->format = r300_translate_zsformat(surf->base.format); @@ -815,7 +822,7 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf) surf->pitch_hiz = tex->tex.hiz_stride_in_pixels[level]; } else { surf->pitch = - tex->tex.stride_in_pixels[level] | + stride | r300_translate_colorformat(surf->base.format) | R300_COLOR_TILE(tex->tex.macrotile[level]) | R300_COLOR_MICROTILE(tex->tex.microtile); @@ -823,7 +830,7 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf) } } -void r300_resource_set_properties(struct pipe_screen *screen, +static void r300_resource_set_properties(struct pipe_screen *screen, struct pipe_resource *tex, const struct pipe_resource *new_properties) { @@ -836,7 +843,6 @@ void r300_resource_set_properties(struct pipe_screen *screen, util_format_short_name(new_properties->format)); r300_texture_desc_init(rscreen, res, new_properties); - r300_texture_setup_format_state(rscreen, res, 0, &res->tx_format); } static void r300_texture_destroy(struct pipe_screen *screen, @@ -995,9 +1001,11 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, /* Not required to implement u_resource_vtbl, consider moving to another file: */ -struct pipe_surface* r300_create_surface(struct pipe_context * ctx, +struct pipe_surface* r300_create_surface_custom(struct pipe_context * ctx, struct pipe_resource* texture, - const struct pipe_surface *surf_tmpl) + const struct pipe_surface *surf_tmpl, + unsigned width0_override, + unsigned height0_override) { struct r300_resource* tex = r300_resource(texture); struct r300_surface* surface = CALLOC_STRUCT(r300_surface); @@ -1012,8 +1020,8 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, pipe_resource_reference(&surface->base.texture, texture); surface->base.context = ctx; surface->base.format = surf_tmpl->format; - surface->base.width = u_minify(texture->width0, level); - surface->base.height = u_minify(texture->height0, level); + surface->base.width = u_minify(width0_override, level); + surface->base.height = u_minify(height0_override, level); surface->base.usage = surf_tmpl->usage; surface->base.u.tex.level = level; surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; @@ -1036,7 +1044,7 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, surface->cbzb_width = align(surface->base.width, 64); /* Height must be aligned to the size of a tile. */ - tile_height = r300_get_pixel_alignment(tex->b.b.b.format, + tile_height = r300_get_pixel_alignment(surface->base.format, tex->b.b.b.nr_samples, tex->tex.microtile, tex->tex.macrotile[level], @@ -1070,6 +1078,15 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx, return &surface->base; } +struct pipe_surface* r300_create_surface(struct pipe_context * ctx, + struct pipe_resource* texture, + const struct pipe_surface *surf_tmpl) +{ + return r300_create_surface_custom(ctx, texture, surf_tmpl, + texture->width0, + texture->height0); +} + /* Not required to implement u_resource_vtbl, consider moving to another file: */ void r300_surface_destroy(struct pipe_context *ctx, struct pipe_surface* s) diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index f87d2842a8b..213bdffc2ed 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -46,10 +46,6 @@ uint32_t r300_translate_texformat(enum pipe_format format, uint32_t r500_tx_format_msb_bit(enum pipe_format format); -void r300_resource_set_properties(struct pipe_screen *screen, - struct pipe_resource *tex, - const struct pipe_resource *new_properties); - boolean r300_is_colorbuffer_format_supported(enum pipe_format format); boolean r300_is_zs_format_supported(enum pipe_format format); @@ -58,7 +54,10 @@ boolean r300_is_sampler_format_supported(enum pipe_format format); void r300_texture_setup_format_state(struct r300_screen *screen, struct r300_resource *tex, + enum pipe_format format, unsigned level, + unsigned width0_override, + unsigned height0_override, struct r300_texture_format_state *out); boolean r300_resource_get_handle(struct pipe_screen* screen, @@ -74,6 +73,11 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen, const struct pipe_resource* templ); +struct pipe_surface* r300_create_surface_custom(struct pipe_context * ctx, + struct pipe_resource* texture, + const struct pipe_surface *surf_tmpl, + unsigned width0_override, + unsigned height0_override); struct pipe_surface* r300_create_surface(struct pipe_context *ctx, struct pipe_resource* texture, diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c index 926bb0b10de..c250bf15604 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.c +++ b/src/gallium/drivers/r300/r300_texture_desc.c @@ -206,8 +206,8 @@ static unsigned r300_texture_get_nblocksy(struct r300_resource *tex, } /* Get a width in pixels from a stride in bytes. */ -static unsigned stride_to_width(enum pipe_format format, - unsigned stride_in_bytes) +unsigned r300_stride_to_width(enum pipe_format format, + unsigned stride_in_bytes) { return (stride_in_bytes / util_format_get_blocksize(format)) * util_format_get_blockwidth(format); @@ -261,7 +261,6 @@ static void r300_setup_miptree(struct r300_screen *screen, tex->tex.size_in_bytes = tex->tex.offset_in_bytes[i] + size; tex->tex.layer_size_in_bytes[i] = layer_size; tex->tex.stride_in_bytes[i] = stride; - tex->tex.stride_in_pixels[i] = stride_to_width(tex->b.b.b.format, stride); tex->tex.cbzb_allowed[i] = tex->tex.cbzb_allowed[i] && aligned_for_cbzb; SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d " @@ -277,7 +276,7 @@ static void r300_setup_flags(struct r300_resource *tex) tex->tex.uses_stride_addressing = !util_is_power_of_two(tex->b.b.b.width0) || (tex->tex.stride_in_bytes_override && - stride_to_width(tex->b.b.b.format, + r300_stride_to_width(tex->b.b.b.format, tex->tex.stride_in_bytes_override) != tex->b.b.b.width0); tex->tex.is_npot = @@ -368,7 +367,9 @@ static void r300_setup_hyperz_properties(struct r300_screen *screen, for (i = 0; i <= tex->b.b.b.last_level; i++) { unsigned zcomp_numdw, zcompsize, hiz_numdw, stride, height; - stride = align(tex->tex.stride_in_pixels[i], 16); + stride = r300_stride_to_width(tex->b.b.b.format, + tex->tex.stride_in_bytes[i]); + stride = align(stride, 16); height = u_minify(tex->b.b.b.height0, i); /* The 8x8 compression mode needs macrotiling. */ @@ -467,7 +468,7 @@ static void r300_tex_print_info(struct r300_resource *tex, func, tex->tex.macrotile[0] ? "YES" : " NO", tex->tex.microtile ? "YES" : " NO", - tex->tex.stride_in_pixels[0], + r300_stride_to_width(tex->b.b.b.format, tex->tex.stride_in_bytes[0]), tex->b.b.b.width0, tex->b.b.b.height0, tex->b.b.b.depth0, tex->b.b.b.last_level, tex->tex.size_in_bytes, util_format_short_name(tex->b.b.b.format)); diff --git a/src/gallium/drivers/r300/r300_texture_desc.h b/src/gallium/drivers/r300/r300_texture_desc.h index 591592dfb04..dd2a07e7022 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.h +++ b/src/gallium/drivers/r300/r300_texture_desc.h @@ -50,4 +50,7 @@ void r300_texture_desc_init(struct r300_screen *rscreen, unsigned r300_texture_get_offset(struct r300_resource *tex, unsigned level, unsigned layer); +unsigned r300_stride_to_width(enum pipe_format format, + unsigned stride_in_bytes); + #endif diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 57d60a0e0fe..afdd530d15d 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -87,9 +87,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, struct r300_resource *tex = r300_resource(texture); struct r300_transfer *trans; struct pipe_resource base; - boolean referenced_cs, referenced_hw, blittable; - const struct util_format_description *desc = - util_format_description(texture->format); + boolean referenced_cs, referenced_hw; referenced_cs = r300->rws->cs_is_buffer_referenced(r300->cs, tex->cs_buf); @@ -100,10 +98,6 @@ r300_texture_get_transfer(struct pipe_context *ctx, r300->rws->buffer_is_busy(tex->buf, RADEON_USAGE_READWRITE); } - blittable = desc->layout == UTIL_FORMAT_LAYOUT_PLAIN || - desc->layout == UTIL_FORMAT_LAYOUT_S3TC || - desc->layout == UTIL_FORMAT_LAYOUT_RGTC; - trans = CALLOC_STRUCT(r300_transfer); if (trans) { /* Initialize the transfer object. */ @@ -116,7 +110,8 @@ r300_texture_get_transfer(struct pipe_context *ctx, * for this transfer. * Also make write transfers pipelined. */ if (tex->tex.microtile || tex->tex.macrotile[level] || - (referenced_hw && blittable && !(usage & PIPE_TRANSFER_READ))) { + (referenced_hw && !(usage & PIPE_TRANSFER_READ) && + r300_is_blit_supported(texture->format))) { if (r300->blitter->running) { fprintf(stderr, "r300: ERROR: Blitter recursion in texture_get_transfer.\n"); os_break();