diff options
Diffstat (limited to 'src/gallium/drivers/radeonsi/r600_texture.c')
-rw-r--r-- | src/gallium/drivers/radeonsi/r600_texture.c | 414 |
1 files changed, 207 insertions, 207 deletions
diff --git a/src/gallium/drivers/radeonsi/r600_texture.c b/src/gallium/drivers/radeonsi/r600_texture.c index 392f177f634..905f2184226 100644 --- a/src/gallium/drivers/radeonsi/r600_texture.c +++ b/src/gallium/drivers/radeonsi/r600_texture.c @@ -66,7 +66,7 @@ static void r600_copy_from_staging_texture(struct pipe_context *ctx, struct r600 0, &sbox); } -unsigned r600_texture_get_offset(struct r600_resource_texture *rtex, +static unsigned r600_texture_get_offset(struct r600_resource_texture *rtex, unsigned level, unsigned layer) { unsigned offset = rtex->offset[level]; @@ -489,15 +489,209 @@ static void r600_texture_destroy(struct pipe_screen *screen, FREE(rtex); } +/* Needs adjustment for pixelformat: + */ +static INLINE unsigned u_box_volume( const struct pipe_box *box ) +{ + return box->width * box->depth * box->height; +}; + +static struct pipe_transfer* si_texture_get_transfer(struct pipe_context *ctx, + struct pipe_resource *texture, + unsigned level, + unsigned usage, + const struct pipe_box *box) +{ + struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; + struct pipe_resource resource; + struct r600_transfer *trans; + int r; + boolean use_staging_texture = FALSE; + + /* We cannot map a tiled texture directly because the data is + * in a different order, therefore we do detiling using a blit. + * + * Also, use a temporary in GTT memory for read transfers, as + * the CPU is much happier reading out of cached system memory + * than uncached VRAM. + */ + if (R600_TEX_IS_TILED(rtex, level)) + use_staging_texture = TRUE; + + if ((usage & PIPE_TRANSFER_READ) && u_box_volume(box) > 1024) + use_staging_texture = TRUE; + + /* XXX: Use a staging texture for uploads if the underlying BO + * is busy. No interface for checking that currently? so do + * it eagerly whenever the transfer doesn't require a readback + * and might block. + */ + if ((usage & PIPE_TRANSFER_WRITE) && + !(usage & (PIPE_TRANSFER_READ | + PIPE_TRANSFER_DONTBLOCK | + PIPE_TRANSFER_UNSYNCHRONIZED))) + use_staging_texture = TRUE; + + if (!permit_hardware_blit(ctx->screen, texture) || + (texture->flags & R600_RESOURCE_FLAG_TRANSFER)) + use_staging_texture = FALSE; + + if (use_staging_texture && (usage & PIPE_TRANSFER_MAP_DIRECTLY)) + return NULL; + + trans = CALLOC_STRUCT(r600_transfer); + if (trans == NULL) + return NULL; + pipe_resource_reference(&trans->transfer.resource, texture); + trans->transfer.level = level; + trans->transfer.usage = usage; + trans->transfer.box = *box; + if (rtex->depth) { + /* XXX: only readback the rectangle which is being mapped? + */ + /* XXX: when discard is true, no need to read back from depth texture + */ + r = r600_texture_depth_flush(ctx, texture, FALSE); + if (r < 0) { + R600_ERR("failed to create temporary texture to hold untiled copy\n"); + pipe_resource_reference(&trans->transfer.resource, NULL); + FREE(trans); + return NULL; + } + trans->transfer.stride = rtex->flushed_depth_texture->pitch_in_bytes[level]; + trans->offset = r600_texture_get_offset(rtex->flushed_depth_texture, level, box->z); + return &trans->transfer; + } else if (use_staging_texture) { + resource.target = PIPE_TEXTURE_2D; + resource.format = texture->format; + resource.width0 = box->width; + resource.height0 = box->height; + resource.depth0 = 1; + resource.array_size = 1; + resource.last_level = 0; + resource.nr_samples = 0; + resource.usage = PIPE_USAGE_STAGING; + resource.bind = 0; + resource.flags = R600_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) { + resource.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) { + resource.bind |= PIPE_BIND_SAMPLER_VIEW; + } + /* Create the temporary texture. */ + trans->staging_texture = ctx->screen->resource_create(ctx->screen, &resource); + if (trans->staging_texture == NULL) { + R600_ERR("failed to create temporary texture to hold untiled copy\n"); + pipe_resource_reference(&trans->transfer.resource, NULL); + FREE(trans); + return NULL; + } + + trans->transfer.stride = + ((struct r600_resource_texture *)trans->staging_texture)->pitch_in_bytes[0]; + if (usage & PIPE_TRANSFER_READ) { + r600_copy_to_staging_texture(ctx, trans); + /* Always referenced in the blit. */ + radeonsi_flush(ctx, NULL, 0); + } + return &trans->transfer; + } + trans->transfer.stride = rtex->pitch_in_bytes[level]; + trans->transfer.layer_stride = rtex->layer_size[level]; + trans->offset = r600_texture_get_offset(rtex, level, box->z); + return &trans->transfer; +} + +static void si_texture_transfer_destroy(struct pipe_context *ctx, + struct pipe_transfer *transfer) +{ + struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; + struct pipe_resource *texture = transfer->resource; + struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; + + if (rtransfer->staging_texture) { + if (transfer->usage & PIPE_TRANSFER_WRITE) { + r600_copy_from_staging_texture(ctx, rtransfer); + } + pipe_resource_reference(&rtransfer->staging_texture, NULL); + } + + if (rtex->depth && !rtex->is_flushing_texture) { + if ((transfer->usage & PIPE_TRANSFER_WRITE) && rtex->flushed_depth_texture) + r600_blit_push_depth(ctx, rtex); + } + + pipe_resource_reference(&transfer->resource, NULL); + FREE(transfer); +} + +static void* si_texture_transfer_map(struct pipe_context *ctx, + struct pipe_transfer* transfer) +{ + struct r600_context *rctx = (struct r600_context *)ctx; + struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; + struct radeon_winsys_cs_handle *buf; + enum pipe_format format = transfer->resource->format; + unsigned offset = 0; + char *map; + + if (rtransfer->staging_texture) { + buf = si_resource(rtransfer->staging_texture)->cs_buf; + } else { + struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource; + + if (rtex->flushed_depth_texture) + buf = si_resource(rtex->flushed_depth_texture)->cs_buf; + else + buf = si_resource(transfer->resource)->cs_buf; + + offset = rtransfer->offset + + transfer->box.y / util_format_get_blockheight(format) * transfer->stride + + transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); + } + + if (!(map = rctx->ws->buffer_map(buf, rctx->cs, transfer->usage))) { + return NULL; + } + + return map + offset; +} + +static void si_texture_transfer_unmap(struct pipe_context *ctx, + struct pipe_transfer* transfer) +{ + struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; + struct r600_context *rctx = (struct r600_context*)ctx; + struct radeon_winsys_cs_handle *buf; + + if (rtransfer->staging_texture) { + buf = si_resource(rtransfer->staging_texture)->cs_buf; + } else { + struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource; + + if (rtex->flushed_depth_texture) { + buf = si_resource(rtex->flushed_depth_texture)->cs_buf; + } else { + buf = si_resource(transfer->resource)->cs_buf; + } + } + rctx->ws->buffer_unmap(buf); +} + static const struct u_resource_vtbl r600_texture_vtbl = { r600_texture_get_handle, /* get_handle */ r600_texture_destroy, /* resource_destroy */ - r600_texture_get_transfer, /* get_transfer */ - r600_texture_transfer_destroy, /* transfer_destroy */ - r600_texture_transfer_map, /* transfer_map */ + si_texture_get_transfer, /* get_transfer */ + si_texture_transfer_destroy, /* transfer_destroy */ + si_texture_transfer_map, /* transfer_map */ u_default_transfer_flush_region,/* transfer_flush_region */ - r600_texture_transfer_unmap, /* transfer_unmap */ + si_texture_transfer_unmap, /* transfer_unmap */ NULL /* transfer_inline_write */ }; @@ -546,7 +740,7 @@ r600_texture_create_object(struct pipe_screen *screen, unsigned base_align = r600_get_base_alignment(screen, ptex->format, array_mode); base_align = rtex->surface.bo_alignment; - if (!r600_init_resource(rscreen, resource, rtex->size, base_align, base->bind, base->usage)) { + if (!si_init_resource(rscreen, resource, rtex->size, base_align, base->bind, base->usage)) { FREE(rtex); return NULL; } @@ -559,8 +753,8 @@ r600_texture_create_object(struct pipe_screen *screen, return rtex; } -struct pipe_resource *r600_texture_create(struct pipe_screen *screen, - const struct pipe_resource *templ) +struct pipe_resource *si_texture_create(struct pipe_screen *screen, + const struct pipe_resource *templ) { struct r600_screen *rscreen = (struct r600_screen*)screen; struct radeon_surface surface; @@ -625,9 +819,9 @@ static void r600_surface_destroy(struct pipe_context *pipe, FREE(surface); } -struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, - const struct pipe_resource *templ, - struct winsys_handle *whandle) +struct pipe_resource *si_texture_from_handle(struct pipe_screen *screen, + const struct pipe_resource *templ, + struct winsys_handle *whandle) { struct r600_screen *rscreen = (struct r600_screen*)screen; struct pb_buffer *buf = NULL; @@ -701,205 +895,11 @@ out: /* XXX: only do this if the depth texture has actually changed: */ - r600_blit_uncompress_depth(ctx, rtex); + si_blit_uncompress_depth(ctx, rtex); return 0; } -/* Needs adjustment for pixelformat: - */ -static INLINE unsigned u_box_volume( const struct pipe_box *box ) -{ - return box->width * box->depth * box->height; -}; - -struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, - struct pipe_resource *texture, - unsigned level, - unsigned usage, - const struct pipe_box *box) -{ - struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; - struct pipe_resource resource; - struct r600_transfer *trans; - int r; - boolean use_staging_texture = FALSE; - - /* We cannot map a tiled texture directly because the data is - * in a different order, therefore we do detiling using a blit. - * - * Also, use a temporary in GTT memory for read transfers, as - * the CPU is much happier reading out of cached system memory - * than uncached VRAM. - */ - if (R600_TEX_IS_TILED(rtex, level)) - use_staging_texture = TRUE; - - if ((usage & PIPE_TRANSFER_READ) && u_box_volume(box) > 1024) - use_staging_texture = TRUE; - - /* XXX: Use a staging texture for uploads if the underlying BO - * is busy. No interface for checking that currently? so do - * it eagerly whenever the transfer doesn't require a readback - * and might block. - */ - if ((usage & PIPE_TRANSFER_WRITE) && - !(usage & (PIPE_TRANSFER_READ | - PIPE_TRANSFER_DONTBLOCK | - PIPE_TRANSFER_UNSYNCHRONIZED))) - use_staging_texture = TRUE; - - if (!permit_hardware_blit(ctx->screen, texture) || - (texture->flags & R600_RESOURCE_FLAG_TRANSFER)) - use_staging_texture = FALSE; - - if (use_staging_texture && (usage & PIPE_TRANSFER_MAP_DIRECTLY)) - return NULL; - - trans = CALLOC_STRUCT(r600_transfer); - if (trans == NULL) - return NULL; - pipe_resource_reference(&trans->transfer.resource, texture); - trans->transfer.level = level; - trans->transfer.usage = usage; - trans->transfer.box = *box; - if (rtex->depth) { - /* XXX: only readback the rectangle which is being mapped? - */ - /* XXX: when discard is true, no need to read back from depth texture - */ - r = r600_texture_depth_flush(ctx, texture, FALSE); - if (r < 0) { - R600_ERR("failed to create temporary texture to hold untiled copy\n"); - pipe_resource_reference(&trans->transfer.resource, NULL); - FREE(trans); - return NULL; - } - trans->transfer.stride = rtex->flushed_depth_texture->pitch_in_bytes[level]; - trans->offset = r600_texture_get_offset(rtex->flushed_depth_texture, level, box->z); - return &trans->transfer; - } else if (use_staging_texture) { - resource.target = PIPE_TEXTURE_2D; - resource.format = texture->format; - resource.width0 = box->width; - resource.height0 = box->height; - resource.depth0 = 1; - resource.array_size = 1; - resource.last_level = 0; - resource.nr_samples = 0; - resource.usage = PIPE_USAGE_STAGING; - resource.bind = 0; - resource.flags = R600_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) { - resource.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) { - resource.bind |= PIPE_BIND_SAMPLER_VIEW; - } - /* Create the temporary texture. */ - trans->staging_texture = ctx->screen->resource_create(ctx->screen, &resource); - if (trans->staging_texture == NULL) { - R600_ERR("failed to create temporary texture to hold untiled copy\n"); - pipe_resource_reference(&trans->transfer.resource, NULL); - FREE(trans); - return NULL; - } - - trans->transfer.stride = - ((struct r600_resource_texture *)trans->staging_texture)->pitch_in_bytes[0]; - if (usage & PIPE_TRANSFER_READ) { - r600_copy_to_staging_texture(ctx, trans); - /* Always referenced in the blit. */ - radeonsi_flush(ctx, NULL, 0); - } - return &trans->transfer; - } - trans->transfer.stride = rtex->pitch_in_bytes[level]; - trans->transfer.layer_stride = rtex->layer_size[level]; - trans->offset = r600_texture_get_offset(rtex, level, box->z); - return &trans->transfer; -} - -void r600_texture_transfer_destroy(struct pipe_context *ctx, - struct pipe_transfer *transfer) -{ - struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; - struct pipe_resource *texture = transfer->resource; - struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; - - if (rtransfer->staging_texture) { - if (transfer->usage & PIPE_TRANSFER_WRITE) { - r600_copy_from_staging_texture(ctx, rtransfer); - } - pipe_resource_reference(&rtransfer->staging_texture, NULL); - } - - if (rtex->depth && !rtex->is_flushing_texture) { - if ((transfer->usage & PIPE_TRANSFER_WRITE) && rtex->flushed_depth_texture) - r600_blit_push_depth(ctx, rtex); - } - - pipe_resource_reference(&transfer->resource, NULL); - FREE(transfer); -} - -void* r600_texture_transfer_map(struct pipe_context *ctx, - struct pipe_transfer* transfer) -{ - struct r600_context *rctx = (struct r600_context *)ctx; - struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; - struct radeon_winsys_cs_handle *buf; - enum pipe_format format = transfer->resource->format; - unsigned offset = 0; - char *map; - - if (rtransfer->staging_texture) { - buf = si_resource(rtransfer->staging_texture)->cs_buf; - } else { - struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource; - - if (rtex->flushed_depth_texture) - buf = si_resource(rtex->flushed_depth_texture)->cs_buf; - else - buf = si_resource(transfer->resource)->cs_buf; - - offset = rtransfer->offset + - transfer->box.y / util_format_get_blockheight(format) * transfer->stride + - transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); - } - - if (!(map = rctx->ws->buffer_map(buf, rctx->cs, transfer->usage))) { - return NULL; - } - - return map + offset; -} - -void r600_texture_transfer_unmap(struct pipe_context *ctx, - struct pipe_transfer* transfer) -{ - struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; - struct r600_context *rctx = (struct r600_context*)ctx; - struct radeon_winsys_cs_handle *buf; - - if (rtransfer->staging_texture) { - buf = si_resource(rtransfer->staging_texture)->cs_buf; - } else { - struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource; - - if (rtex->flushed_depth_texture) { - buf = si_resource(rtex->flushed_depth_texture)->cs_buf; - } else { - buf = si_resource(transfer->resource)->cs_buf; - } - } - rctx->ws->buffer_unmap(buf); -} - -void r600_init_surface_functions(struct r600_context *r600) +void si_init_surface_functions(struct r600_context *r600) { r600->context.create_surface = r600_create_surface; r600->context.surface_destroy = r600_surface_destroy; |