X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fr300%2Fr300_transfer.c;h=02421a58b835ad82398ac5a27033e8141f1323da;hb=0e6d7ce0178d65787e3e10f56638c2f0a88296f1;hp=0dae9ef98b739473185edaa6034ae8dae17be9a5;hpb=c7f5c9a3dc6350252e73b541bb85ab3ed9e64a9c;p=mesa.git diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 0dae9ef98b7..02421a58b83 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -21,12 +21,9 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "r300_context.h" #include "r300_transfer.h" #include "r300_texture.h" -#include "r300_screen.h" - -#include "r300_winsys.h" +#include "r300_screen_buffer.h" #include "util/u_memory.h" #include "util/u_format.h" @@ -40,9 +37,6 @@ struct r300_transfer { /* Detiled texture. */ struct r300_texture *detiled_texture; - - /* Transfer and format flags. */ - unsigned render_target_usage; }; /* Convenience cast wrapper. */ @@ -56,63 +50,38 @@ r300_transfer(struct pipe_transfer* transfer) static void r300_copy_from_tiled_texture(struct pipe_context *ctx, struct r300_transfer *r300transfer) { - struct pipe_screen *screen = ctx->screen; struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; struct pipe_resource *tex = transfer->resource; - struct pipe_surface *src, *dst; - - src = screen->get_tex_surface(screen, tex, - transfer->sr.face, - transfer->sr.level, - transfer->box.z, - PIPE_BIND_BLIT_SOURCE); + struct pipe_subresource subdst; - dst = screen->get_tex_surface(screen, &r300transfer->detiled_texture->b.b, - 0, 0, 0, - PIPE_BIND_BLIT_DESTINATION); + subdst.face = 0; + subdst.level = 0; - ctx->surface_copy(ctx, dst, 0, 0, src, - transfer->box.x, transfer->box.y, - transfer->box.width, transfer->box.height); - - pipe_surface_reference(&src, NULL); - pipe_surface_reference(&dst, NULL); + ctx->resource_copy_region(ctx, &r300transfer->detiled_texture->b.b, subdst, + 0, 0, 0, + tex, transfer->sr, + transfer->box.x, transfer->box.y, transfer->box.z, + transfer->box.width, transfer->box.height); } /* Copy a detiled texture to a tiled one. */ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, struct r300_transfer *r300transfer) { - struct pipe_screen *screen = ctx->screen; struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; struct pipe_resource *tex = transfer->resource; - struct pipe_surface *src, *dst; + struct pipe_subresource subsrc; - src = screen->get_tex_surface(screen, &r300transfer->detiled_texture->b.b, - 0, 0, 0, - PIPE_BIND_BLIT_SOURCE); + subsrc.face = 0; + subsrc.level = 0; - dst = screen->get_tex_surface(screen, tex, - transfer->sr.face, - transfer->sr.level, - transfer->box.z, - PIPE_BIND_BLIT_DESTINATION); + ctx->resource_copy_region(ctx, tex, transfer->sr, + transfer->box.x, transfer->box.y, transfer->box.z, + &r300transfer->detiled_texture->b.b, subsrc, + 0, 0, 0, + transfer->box.width, transfer->box.height); - /* XXX this flush prevents the following DRM error from occuring: - * [drm:radeon_cs_ioctl] *ERROR* Failed to parse relocation ! - * Reproducible with perf/copytex. */ ctx->flush(ctx, 0, NULL); - - ctx->surface_copy(ctx, dst, - transfer->box.x, transfer->box.y, - src, 0, 0, - transfer->box.width, transfer->box.height); - - /* XXX this flush fixes a few piglit tests (e.g. glean/pixelFormats). */ - ctx->flush(ctx, 0, NULL); - - pipe_surface_reference(&src, NULL); - pipe_surface_reference(&dst, NULL); } struct pipe_transfer* @@ -126,6 +95,20 @@ r300_texture_get_transfer(struct pipe_context *ctx, struct r300_screen *r300screen = r300_screen(ctx->screen); struct r300_transfer *trans; struct pipe_resource base; + boolean referenced_cs, referenced_hw, blittable; + + referenced_cs = r300screen->rws->is_buffer_referenced( + r300screen->rws, tex->buffer, R300_REF_CS); + if (referenced_cs) { + referenced_hw = TRUE; + } else { + referenced_hw = r300screen->rws->is_buffer_referenced( + r300screen->rws, tex->buffer, R300_REF_HW); + } + + blittable = ctx->screen->is_format_supported( + ctx->screen, texture->format, texture->target, 0, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 0); trans = CALLOC_STRUCT(r300_transfer); if (trans) { @@ -136,13 +119,10 @@ r300_texture_get_transfer(struct pipe_context *ctx, trans->transfer.box = *box; /* If the texture is tiled, we must create a temporary detiled texture - * for this transfer. */ - if (tex->microtile || tex->macrotile) { - trans->render_target_usage = - util_format_is_depth_or_stencil(texture->format) ? - PIPE_BIND_DEPTH_STENCIL : - PIPE_BIND_RENDER_TARGET; - + * for this transfer. + * Also make write transfers pipelined. */ + if (tex->microtile || tex->macrotile || + ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) { base.target = PIPE_TEXTURE_2D; base.format = texture->format; base.width0 = box->width; @@ -157,7 +137,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, /* For texture reading, the temporary (detiled) texture is used as * a render target when blitting from a tiled texture. */ if (usage & PIPE_TRANSFER_READ) { - base.bind |= trans->render_target_usage; + base.bind |= PIPE_BIND_RENDER_TARGET; } /* For texture writing, the temporary texture is used as a sampler * when blitting into a tiled texture. */ @@ -170,6 +150,30 @@ r300_texture_get_transfer(struct pipe_context *ctx, ctx->screen->resource_create(ctx->screen, &base)); + if (!trans->detiled_texture) { + /* Oh crap, the thing can't create the texture. + * Let's flush and try again. */ + ctx->flush(ctx, 0, NULL); + + trans->detiled_texture = r300_texture( + ctx->screen->resource_create(ctx->screen, + &base)); + + if (!trans->detiled_texture) { + /* For linear textures, it's safe to fallback to + * an unpipelined transfer. */ + if (!tex->microtile && !tex->macrotile) { + goto unpipelined; + } + + /* Otherwise, go to hell. */ + fprintf(stderr, + "r300: Failed to create a transfer object, praise.\n"); + FREE(trans); + return NULL; + } + } + assert(!trans->detiled_texture->microtile && !trans->detiled_texture->macrotile); @@ -187,14 +191,24 @@ r300_texture_get_transfer(struct pipe_context *ctx, /* We cannot map a tiled texture directly because the data is * in a different order, therefore we do detiling using a blit. */ r300_copy_from_tiled_texture(ctx, trans); + + /* Always referenced in the blit. */ + ctx->flush(ctx, 0, NULL); } - } else { - trans->transfer.stride = - r300_texture_get_stride(r300screen, tex, sr.level); - trans->offset = r300_texture_get_offset(tex, sr.level, box->z, sr.face); + return &trans->transfer; } + + unpipelined: + /* Unpipelined transfer. */ + trans->transfer.stride = + r300_texture_get_stride(r300screen, tex, sr.level); + trans->offset = r300_texture_get_offset(tex, sr.level, box->z, sr.face); + + if (referenced_cs && (usage & PIPE_TRANSFER_READ)) + ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); + return &trans->transfer; } - return &trans->transfer; + return NULL; } void r300_texture_transfer_destroy(struct pipe_context *ctx, @@ -257,4 +271,3 @@ void r300_texture_transfer_unmap(struct pipe_context *ctx, rws->buffer_unmap(rws, tex->buffer); } } -