diff options
Diffstat (limited to 'src/gallium/drivers/r300/r300_transfer.c')
-rw-r--r-- | src/gallium/drivers/r300/r300_transfer.c | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 0d88d745c0..02421a58b8 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -57,22 +57,11 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx, 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. */ } /* Copy a detiled texture to a tiled one. */ @@ -92,7 +81,6 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, 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); } @@ -107,7 +95,7 @@ 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; + boolean referenced_cs, referenced_hw, blittable; referenced_cs = r300screen->rws->is_buffer_referenced( r300screen->rws, tex->buffer, R300_REF_CS); @@ -118,6 +106,10 @@ r300_texture_get_transfer(struct pipe_context *ctx, 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) { /* Initialize the transfer object. */ @@ -130,7 +122,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, * for this transfer. * Also make write transfers pipelined. */ if (tex->microtile || tex->macrotile || - (referenced_hw & !(usage & PIPE_TRANSFER_READ))) { + ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) { base.target = PIPE_TEXTURE_2D; base.format = texture->format; base.width0 = box->width; @@ -158,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); @@ -179,16 +195,20 @@ r300_texture_get_transfer(struct pipe_context *ctx, /* Always referenced in the blit. */ ctx->flush(ctx, 0, NULL); } - } else { - trans->transfer.stride = + 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); + 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); - } + 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, |