X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fr300%2Fr300_transfer.c;h=95cea7265512fb53b3d95b57c6e92058443b23ec;hb=b80aff88fed60679d2b0ac7fcea29d6cd3ad95ce;hp=4f37fabb28984dcaa4212070bf8ff8b231b2aac8;hpb=9be40de0871980ca541f0682aef6c1c507c1610f;p=mesa.git diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 4f37fabb289..95cea726551 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -22,11 +22,12 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "r300_transfer.h" -#include "r300_texture.h" +#include "r300_texture_desc.h" #include "r300_screen_buffer.h" #include "util/u_memory.h" -#include "util/u_format.h" +#include "util/format/u_format.h" +#include "util/u_box.h" struct r300_transfer { /* Parent class */ @@ -35,12 +36,12 @@ 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. */ -static INLINE struct r300_transfer* +static inline struct r300_transfer* r300_transfer(struct pipe_transfer* transfer) { return (struct r300_transfer*)transfer; @@ -51,28 +52,31 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx, struct r300_transfer *r300transfer) { struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; - struct pipe_resource *tex = transfer->resource; - struct pipe_subresource subdst; - - subdst.face = 0; - subdst.level = 0; - - /* XXX if we don't flush before copying the texture and mapping it, - * we get wrong pixels, i.e. it's like latest draw calls didn't happen, - * including this blit. Tests: e.g. piglit/provoking-vertex - * - * Since the flush immediately before mapping is implicit (the buffer is - * always referenced in resource_copy_region), every read transfer costs - * 2 flushes. That sucks. */ - ctx->flush(ctx, 0, 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); - - /* Flushing after the copy is implicit, issued by winsys. */ + struct pipe_resource *src = transfer->resource; + struct pipe_resource *dst = &r300transfer->linear_texture->b.b; + + if (src->nr_samples <= 1) { + ctx->resource_copy_region(ctx, dst, 0, 0, 0, 0, + src, transfer->level, &transfer->box); + } else { + /* Resolve the resource. */ + struct pipe_blit_info blit; + + memset(&blit, 0, sizeof(blit)); + blit.src.resource = src; + blit.src.format = src->format; + blit.src.level = transfer->level; + blit.src.box = transfer->box; + blit.dst.resource = dst; + blit.dst.format = dst->format; + blit.dst.box.width = transfer->box.width; + blit.dst.box.height = transfer->box.height; + blit.dst.box.depth = transfer->box.depth; + blit.mask = PIPE_MASK_RGBA; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + ctx->blit(ctx, &blit); + } } /* Copy a detiled texture to a tiled one. */ @@ -81,123 +85,114 @@ 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; - subsrc.face = 0; - subsrc.level = 0; + u_box_3d(0, 0, 0, + transfer->box.width, transfer->box.height, transfer->box.depth, + &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); + ctx->resource_copy_region(ctx, tex, transfer->level, + transfer->box.x, transfer->box.y, transfer->box.z, + &r300transfer->linear_texture->b.b, 0, &src_box); - /* 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) +void * +r300_texture_transfer_map(struct pipe_context *ctx, + struct pipe_resource *texture, + unsigned level, + unsigned usage, + const struct pipe_box *box, + struct pipe_transfer **transfer) { - 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; + boolean referenced_cs, referenced_hw; + enum pipe_format format = tex->b.b.format; + char *map; - referenced_cs = r300screen->rws->is_buffer_referenced( - r300screen->rws, tex->buffer, R300_REF_CS); + referenced_cs = + r300->rws->cs_is_buffer_referenced(r300->cs, tex->buf, RADEON_USAGE_READWRITE); if (referenced_cs) { referenced_hw = TRUE; } else { - referenced_hw = r300screen->rws->is_buffer_referenced( - r300screen->rws, tex->buffer, R300_REF_HW); + referenced_hw = + !r300->rws->buffer_wait(tex->buf, 0, RADEON_USAGE_READWRITE); } - 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) { /* Initialize the transfer object. */ - pipe_resource_reference(&trans->transfer.resource, texture); - trans->transfer.sr = sr; + trans->transfer.resource = texture; + 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. * Also make write transfers pipelined. */ - if (tex->microtile || tex->macrotile || - ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) { + if (tex->tex.microtile || tex->tex.macrotile[level] || + (referenced_hw && !(usage & PIPE_TRANSFER_READ) && + r300_is_blit_supported(texture->format))) { + struct pipe_resource base; + + if (r300->blitter->running) { + fprintf(stderr, "r300: ERROR: Blitter recursion in texture_get_transfer.\n"); + os_break(); + } + + memset(&base, 0, sizeof(base)); base.target = PIPE_TEXTURE_2D; base.format = texture->format; base.width0 = box->width; base.height0 = box->height; - base.depth0 = 0; - base.last_level = 0; - base.nr_samples = 0; - base.usage = PIPE_USAGE_DYNAMIC; - base.bind = 0; - 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. */ - if (usage & PIPE_TRANSFER_READ) { - base.bind |= PIPE_BIND_RENDER_TARGET; - } - /* For texture writing, the temporary texture is used as a sampler - * when blitting into a tiled texture. */ - if (usage & PIPE_TRANSFER_WRITE) { - base.bind |= PIPE_BIND_SAMPLER_VIEW; + base.depth0 = 1; + base.array_size = 1; + base.usage = PIPE_USAGE_STAGING; + base.flags = R300_RESOURCE_FLAG_TRANSFER; + + /* We must set the correct texture target and dimensions if needed for a 3D transfer. */ + if (box->depth > 1 && util_max_layer(texture, level) > 0) { + base.target = texture->target; + + if (base.target == PIPE_TEXTURE_3D) { + base.depth0 = util_next_power_of_two(box->depth); + } } /* Create the temporary texture. */ - trans->detiled_texture = r300_texture( + trans->linear_texture = r300_resource( ctx->screen->resource_create(ctx->screen, &base)); - if (!trans->detiled_texture) { + if (!trans->linear_texture) { /* Oh crap, the thing can't create the texture. * Let's flush and try again. */ - ctx->flush(ctx, 0, NULL); + r300_flush(ctx, 0, NULL); - trans->detiled_texture = r300_texture( + trans->linear_texture = r300_resource( 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. */ + if (!trans->linear_texture) { fprintf(stderr, - "r300: Failed to create a transfer object, praise.\n"); + "r300: Failed to create a transfer object.\n"); FREE(trans); return NULL; } } - assert(!trans->detiled_texture->microtile && - !trans->detiled_texture->macrotile); + 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]; + trans->transfer.layer_stride = + trans->linear_texture->tex.layer_size_in_bytes[0]; if (usage & PIPE_TRANSFER_READ) { /* We cannot map a tiled texture directly because the data is @@ -205,81 +200,61 @@ r300_texture_get_transfer(struct pipe_context *ctx, r300_copy_from_tiled_texture(ctx, trans); /* Always referenced in the blit. */ - ctx->flush(ctx, 0, NULL); + r300_flush(ctx, 0, NULL); + } + } else { + /* Unpipelined transfer. */ + trans->transfer.stride = tex->tex.stride_in_bytes[level]; + trans->transfer.layer_stride = tex->tex.layer_size_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; - } - - 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 NULL; -} - -void r300_texture_transfer_destroy(struct pipe_context *ctx, - struct pipe_transfer *trans) -{ - struct r300_transfer *r300transfer = r300_transfer(trans); - - if (r300transfer->detiled_texture) { - if (trans->usage & PIPE_TRANSFER_WRITE) { - r300_copy_into_tiled_texture(ctx, r300transfer); } - - pipe_resource_reference( - (struct pipe_resource**)&r300transfer->detiled_texture, NULL); } - pipe_resource_reference(&trans->resource, NULL); - FREE(trans); -} -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_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = r300_texture(transfer->resource); - char *map; - enum pipe_format format = tex->b.b.format; - - if (r300transfer->detiled_texture) { + if (trans->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, - transfer->usage); + map = r300->rws->buffer_map(trans->linear_texture->buf, + r300->cs, usage); + if (!map) { + pipe_resource_reference( + (struct pipe_resource**)&trans->linear_texture, NULL); + FREE(trans); + return NULL; + } + *transfer = &trans->transfer; + return map; } else { /* Tiling is disabled. */ - map = rws->buffer_map(rws, tex->buffer, - transfer->usage); - + map = r300->rws->buffer_map(tex->buf, r300->cs, usage); if (!map) { + FREE(trans); return NULL; } - return map + r300_transfer(transfer)->offset + - transfer->box.y / util_format_get_blockheight(format) * transfer->stride + - transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); + *transfer = &trans->transfer; + return map + trans->offset + + box->y / util_format_get_blockheight(format) * trans->transfer.stride + + box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); } } 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 r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = r300_texture(transfer->resource); + struct r300_transfer *trans = r300_transfer(transfer); - if (r300transfer->detiled_texture) { - rws->buffer_unmap(rws, r300transfer->detiled_texture->buffer); - } else { - rws->buffer_unmap(rws, tex->buffer); + if (trans->linear_texture) { + if (transfer->usage & PIPE_TRANSFER_WRITE) { + r300_copy_into_tiled_texture(ctx, trans); + } + + pipe_resource_reference( + (struct pipe_resource**)&trans->linear_texture, NULL); } + FREE(transfer); }