X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fr300%2Fr300_transfer.c;h=e2ea4cbf6c5458aacbb7541ba97dcfdefb1c18b6;hb=fe622bac0c1b5b9f2a9fcf9f35b51232a06bea42;hp=22dff41ccec8835d24fca11458c592472f080ff7;hpb=9f8dbd33961e12887ee4f9521be30c6c94e81a5d;p=mesa.git diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 22dff41ccec..e2ea4cbf6c5 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -21,15 +21,13 @@ * 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_texture_desc.h" +#include "r300_screen_buffer.h" #include "util/u_memory.h" #include "util/u_format.h" +#include "util/u_box.h" struct r300_transfer { /* Parent class */ @@ -38,8 +36,8 @@ struct r300_transfer { /* Offset from start of buffer. */ unsigned offset; - /* Detiled texture. */ - struct r300_texture *detiled_texture; + /* Linear texture. */ + struct r300_resource *linear_texture; }; /* Convenience cast wrapper. */ @@ -55,16 +53,10 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx, { struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; struct pipe_resource *tex = transfer->resource; - struct pipe_subresource subdst; - - subdst.face = 0; - subdst.level = 0; - 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); + ctx->resource_copy_region(ctx, &r300transfer->linear_texture->b.b.b, 0, + 0, 0, 0, + tex, transfer->level, &transfer->box); } /* Copy a detiled texture to a tiled one. */ @@ -73,60 +65,74 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, { struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; struct pipe_resource *tex = transfer->resource; - struct pipe_subresource subsrc; + struct pipe_box src_box; + u_box_origin_2d(transfer->box.width, transfer->box.height, &src_box); - subsrc.face = 0; - subsrc.level = 0; + ctx->resource_copy_region(ctx, tex, transfer->level, + transfer->box.x, transfer->box.y, transfer->box.z, + &r300transfer->linear_texture->b.b.b, 0, &src_box); - 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 fixes a few piglit tests (e.g. glean/pixelFormats). */ - ctx->flush(ctx, 0, NULL); + /* XXX remove this. */ + r300_flush(ctx, 0, NULL); } struct pipe_transfer* r300_texture_get_transfer(struct pipe_context *ctx, - struct pipe_resource *texture, - struct pipe_subresource sr, - unsigned usage, - const struct pipe_box *box) + struct pipe_resource *texture, + unsigned level, + unsigned usage, + const struct pipe_box *box) { - struct r300_texture *tex = r300_texture(texture); - struct r300_screen *r300screen = r300_screen(ctx->screen); + struct r300_context *r300 = r300_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); + + referenced_cs = + r300->rws->cs_is_buffer_referenced(r300->cs, tex->cs_buf); + if (referenced_cs) { + referenced_hw = TRUE; + } else { + referenced_hw = + r300->rws->buffer_is_busy(tex->buf); + } - /* XXX Why aren't flushes taken care of by winsys automatically? - * Winsys seems to sometimes return a cached buffer instead of - * a mapped hardware buffer if this flush is commented out. */ - if (ctx->is_resource_referenced(ctx, texture, sr.face, sr.level)) - ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); + 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. */ pipe_resource_reference(&trans->transfer.resource, texture); - trans->transfer.sr = sr; + trans->transfer.level = level; trans->transfer.usage = usage; trans->transfer.box = *box; /* If the texture is tiled, we must create a temporary detiled texture - * for this transfer. */ - if (tex->microtile || tex->macrotile) { + * for this transfer. + * Also make write transfers pipelined. */ + if (tex->tex.microtile || tex->tex.macrotile[level] || + (referenced_hw && blittable && !(usage & PIPE_TRANSFER_READ))) { + if (r300->blitter->running) { + fprintf(stderr, "r300: ERROR: Blitter recursion in texture_get_transfer.\n"); + os_break(); + } + base.target = PIPE_TEXTURE_2D; base.format = texture->format; base.width0 = box->width; base.height0 = box->height; - base.depth0 = 0; + base.depth0 = 1; + base.array_size = 1; base.last_level = 0; base.nr_samples = 0; base.usage = PIPE_USAGE_DYNAMIC; base.bind = 0; - base.flags = R300_RESOURCE_FLAG_TRANSFER; + base.flags = R300_RESOURCE_FLAG_TRANSFER; /* For texture reading, the temporary (detiled) texture is used as * a render target when blitting from a tiled texture. */ @@ -140,35 +146,63 @@ r300_texture_get_transfer(struct pipe_context *ctx, } /* Create the temporary texture. */ - trans->detiled_texture = r300_texture( + trans->linear_texture = r300_resource( ctx->screen->resource_create(ctx->screen, &base)); - assert(!trans->detiled_texture->microtile && - !trans->detiled_texture->macrotile); + if (!trans->linear_texture) { + /* Oh crap, the thing can't create the texture. + * Let's flush and try again. */ + r300_flush(ctx, 0, NULL); + + trans->linear_texture = r300_resource( + ctx->screen->resource_create(ctx->screen, + &base)); + + if (!trans->linear_texture) { + /* For linear textures, it's safe to fallback to + * an unpipelined transfer. */ + if (!tex->tex.microtile && !tex->tex.macrotile[level]) { + goto unpipelined; + } + + /* Otherwise, go to hell. */ + fprintf(stderr, + "r300: Failed to create a transfer object, praise.\n"); + FREE(trans); + return NULL; + } + } + + assert(!trans->linear_texture->tex.microtile && + !trans->linear_texture->tex.macrotile[0]); - /* Set the stride. - * - * Even though we are using an internal texture for this, - * the transfer sr, box and usage parameters still reflect - * the arguments received to get_transfer. We just do the - * right thing internally. - */ + /* Set the stride. */ trans->transfer.stride = - r300_texture_get_stride(r300screen, trans->detiled_texture, 0); + trans->linear_texture->tex.stride_in_bytes[0]; if (usage & PIPE_TRANSFER_READ) { /* 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. */ + r300_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 = tex->tex.stride_in_bytes[level]; + trans->offset = r300_texture_get_offset(tex, level, box->z); + + if (referenced_cs && + !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) + r300_flush(ctx, 0, NULL); + return &trans->transfer; } - return &trans->transfer; + return NULL; } void r300_texture_transfer_destroy(struct pipe_context *ctx, @@ -176,13 +210,13 @@ void r300_texture_transfer_destroy(struct pipe_context *ctx, { struct r300_transfer *r300transfer = r300_transfer(trans); - if (r300transfer->detiled_texture) { + if (r300transfer->linear_texture) { if (trans->usage & PIPE_TRANSFER_WRITE) { r300_copy_into_tiled_texture(ctx, r300transfer); } pipe_resource_reference( - (struct pipe_resource**)&r300transfer->detiled_texture, NULL); + (struct pipe_resource**)&r300transfer->linear_texture, NULL); } pipe_resource_reference(&trans->resource, NULL); FREE(trans); @@ -191,21 +225,22 @@ void r300_texture_transfer_destroy(struct pipe_context *ctx, void* r300_texture_transfer_map(struct pipe_context *ctx, struct pipe_transfer *transfer) { - struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; + struct r300_context *r300 = r300_context(ctx); + struct radeon_winsys *rws = (struct radeon_winsys *)ctx->winsys; struct r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = r300_texture(transfer->resource); + struct r300_resource *tex = r300_resource(transfer->resource); char *map; - enum pipe_format format = tex->b.b.format; + enum pipe_format format = tex->b.b.b.format; - if (r300transfer->detiled_texture) { + if (r300transfer->linear_texture) { /* The detiled texture is of the same size as the region being mapped * (no offset needed). */ - return rws->buffer_map(rws, - r300transfer->detiled_texture->buffer, + return rws->buffer_map(r300transfer->linear_texture->buf, + r300->cs, transfer->usage); } else { /* Tiling is disabled. */ - map = rws->buffer_map(rws, tex->buffer, + map = rws->buffer_map(tex->buf, r300->cs, transfer->usage); if (!map) { @@ -221,13 +256,13 @@ void* r300_texture_transfer_map(struct pipe_context *ctx, void r300_texture_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer *transfer) { - struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; + struct radeon_winsys *rws = (struct radeon_winsys *)ctx->winsys; struct r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = r300_texture(transfer->resource); + struct r300_resource *tex = r300_resource(transfer->resource); - if (r300transfer->detiled_texture) { - rws->buffer_unmap(rws, r300transfer->detiled_texture->buffer); + if (r300transfer->linear_texture) { + rws->buffer_unmap(r300transfer->linear_texture->buf); } else { - rws->buffer_unmap(rws, tex->buffer); + rws->buffer_unmap(tex->buf); } }