diff options
author | Chia-I Wu <[email protected]> | 2013-05-13 14:29:09 +0800 |
---|---|---|
committer | Chia-I Wu <[email protected]> | 2013-05-14 16:01:20 +0800 |
commit | 528ac68f7a5225be5d624b6eca91be11122dfa91 (patch) | |
tree | 1a8281fa77c740428fe4a2a2aa0a37f713a7c867 /src/gallium/drivers/ilo/ilo_resource.c | |
parent | 888fc7a89197972aac614fc19d1c82ed1adbb3f2 (diff) |
ilo: move transfer-related functions to a new file
Resource mapping is distinct from resource allocation, and is going to get
more and more complex. Move the related functions to a new file to make the
separation clear.
Diffstat (limited to 'src/gallium/drivers/ilo/ilo_resource.c')
-rw-r--r-- | src/gallium/drivers/ilo/ilo_resource.c | 450 |
1 files changed, 3 insertions, 447 deletions
diff --git a/src/gallium/drivers/ilo/ilo_resource.c b/src/gallium/drivers/ilo/ilo_resource.c index 41e4ffb1a9b..96f9d003793 100644 --- a/src/gallium/drivers/ilo/ilo_resource.c +++ b/src/gallium/drivers/ilo/ilo_resource.c @@ -25,38 +25,12 @@ * Chia-I Wu <[email protected]> */ -#include "util/u_surface.h" -#include "util/u_transfer.h" -#include "util/u_format_etc.h" - -#include "ilo_cp.h" -#include "ilo_context.h" #include "ilo_screen.h" #include "ilo_resource.h" /* use PIPE_BIND_CUSTOM to indicate MCS */ #define ILO_BIND_MCS PIPE_BIND_CUSTOM -enum ilo_transfer_map_method { - ILO_TRANSFER_MAP_DIRECT, - ILO_TRANSFER_MAP_STAGING_SYS, -}; - -struct ilo_transfer { - struct pipe_transfer base; - - enum ilo_transfer_map_method method; - void *ptr; - - void *staging_sys; -}; - -static inline struct ilo_transfer * -ilo_transfer(struct pipe_transfer *transfer) -{ - return (struct ilo_transfer *) transfer; -} - static struct intel_bo * alloc_buf_bo(const struct ilo_resource *res) { @@ -162,8 +136,8 @@ alloc_tex_bo(const struct ilo_resource *res) return bo; } -static bool -realloc_bo(struct ilo_resource *res) +bool +ilo_resource_alloc_bo(struct ilo_resource *res) { struct intel_bo *old_bo = res->bo; @@ -191,412 +165,6 @@ realloc_bo(struct ilo_resource *res) return true; } -static void -ilo_transfer_inline_write(struct pipe_context *pipe, - struct pipe_resource *r, - unsigned level, - unsigned usage, - const struct pipe_box *box, - const void *data, - unsigned stride, - unsigned layer_stride) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_resource *res = ilo_resource(r); - int offset, size; - bool will_be_busy; - - /* - * Fall back to map(), memcpy(), and unmap(). We use this path for - * unsynchronized write, as the buffer is likely to be busy and pwrite() - * will stall. - */ - if (unlikely(res->base.target != PIPE_BUFFER) || - (usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { - u_default_transfer_inline_write(pipe, r, - level, usage, box, data, stride, layer_stride); - - return; - } - - /* - * XXX With hardware context support, the bo may be needed by GPU without - * being referenced by ilo->cp->bo. We have to flush unconditionally, and - * that is bad. - */ - if (ilo->cp->hw_ctx) - ilo_cp_flush(ilo->cp); - - will_be_busy = ilo->cp->bo->references(ilo->cp->bo, res->bo); - - /* see if we can avoid stalling */ - if (will_be_busy || intel_bo_is_busy(res->bo)) { - bool will_stall = true; - - if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { - /* old data not needed so discard the old bo to avoid stalling */ - if (realloc_bo(res)) - will_stall = false; - } - else { - /* - * We could allocate a temporary bo to hold the data and emit - * pipelined copy blit to move them to res->bo. But for now, do - * nothing. - */ - } - - /* flush to make bo busy (so that pwrite() stalls as it should be) */ - if (will_stall && will_be_busy) - ilo_cp_flush(ilo->cp); - } - - /* for PIPE_BUFFERs, conversion should not be needed */ - assert(res->bo_format == res->base.format); - - /* they should specify just an offset and a size */ - assert(level == 0); - assert(box->y == 0); - assert(box->z == 0); - assert(box->height == 1); - assert(box->depth == 1); - offset = box->x; - size = box->width; - - res->bo->pwrite(res->bo, offset, size, data); -} - -static void -transfer_unmap_sys_convert(enum pipe_format dst_fmt, - const struct pipe_transfer *dst_xfer, - void *dst, - enum pipe_format src_fmt, - const struct pipe_transfer *src_xfer, - const void *src) -{ - int i; - - switch (src_fmt) { - case PIPE_FORMAT_ETC1_RGB8: - assert(dst_fmt == PIPE_FORMAT_R8G8B8X8_UNORM); - - for (i = 0; i < dst_xfer->box.depth; i++) { - util_format_etc1_rgb8_unpack_rgba_8unorm(dst, - dst_xfer->stride, src, src_xfer->stride, - dst_xfer->box.width, dst_xfer->box.height); - - dst += dst_xfer->layer_stride; - src += src_xfer->layer_stride; - } - break; - default: - assert(!"unable to convert the staging data"); - break; - } -} - -static void -transfer_unmap_sys(struct ilo_context *ilo, - struct ilo_resource *res, - struct ilo_transfer *xfer) -{ - const void *src = xfer->ptr; - struct pipe_transfer *dst_xfer; - void *dst; - - dst = ilo->base.transfer_map(&ilo->base, - xfer->base.resource, xfer->base.level, - PIPE_TRANSFER_WRITE | - PIPE_TRANSFER_MAP_DIRECTLY | - PIPE_TRANSFER_DISCARD_RANGE, - &xfer->base.box, &dst_xfer); - if (!dst_xfer) { - ilo_err("failed to map resource for moving staging data\n"); - FREE(xfer->staging_sys); - return; - } - - if (likely(res->bo_format != res->base.format)) { - transfer_unmap_sys_convert(res->bo_format, dst_xfer, dst, - res->base.format, &xfer->base, src); - } - else { - util_copy_box(dst, res->bo_format, - dst_xfer->stride, dst_xfer->layer_stride, 0, 0, 0, - dst_xfer->box.width, dst_xfer->box.height, dst_xfer->box.depth, - src, xfer->base.stride, xfer->base.layer_stride, 0, 0, 0); - } - - ilo->base.transfer_unmap(&ilo->base, dst_xfer); - FREE(xfer->staging_sys); -} - -static bool -transfer_map_sys(struct ilo_context *ilo, - struct ilo_resource *res, - struct ilo_transfer *xfer) -{ - const struct pipe_box *box = &xfer->base.box; - const size_t stride = util_format_get_stride(res->base.format, box->width); - const size_t size = - util_format_get_2d_size(res->base.format, stride, box->height); - bool read_back = false; - - if (xfer->base.usage & PIPE_TRANSFER_READ) { - read_back = true; - } - else if (xfer->base.usage & PIPE_TRANSFER_WRITE) { - const unsigned discard_flags = - (PIPE_TRANSFER_DISCARD_RANGE | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE); - - if (!(xfer->base.usage & discard_flags)) - read_back = true; - } - - /* TODO */ - if (read_back) - return false; - - xfer->staging_sys = MALLOC(size * box->depth); - if (!xfer->staging_sys) - return false; - - xfer->base.stride = stride; - xfer->base.layer_stride = size; - xfer->ptr = xfer->staging_sys; - - return true; -} - -static void -transfer_unmap_direct(struct ilo_context *ilo, - struct ilo_resource *res, - struct ilo_transfer *xfer) -{ - res->bo->unmap(res->bo); -} - -static bool -transfer_map_direct(struct ilo_context *ilo, - struct ilo_resource *res, - struct ilo_transfer *xfer) -{ - int x, y, err; - - if (xfer->base.usage & PIPE_TRANSFER_UNSYNCHRONIZED) - err = res->bo->map_unsynchronized(res->bo); - /* prefer map() when there is the last-level cache */ - else if (res->tiling == INTEL_TILING_NONE && - (ilo->dev->has_llc || (xfer->base.usage & PIPE_TRANSFER_READ))) - err = res->bo->map(res->bo, (xfer->base.usage & PIPE_TRANSFER_WRITE)); - else - err = res->bo->map_gtt(res->bo); - - if (err) - return false; - - /* note that stride is for a block row, not a texel row */ - xfer->base.stride = res->bo_stride; - - /* - * we can walk through layers when the resource is a texture array or - * when this is the first level of a 3D texture being mapped - */ - if (res->base.array_size > 1 || - (res->base.target == PIPE_TEXTURE_3D && xfer->base.level == 0)) { - const unsigned qpitch = res->slice_offsets[xfer->base.level][1].y - - res->slice_offsets[xfer->base.level][0].y; - - assert(qpitch % res->block_height == 0); - xfer->base.layer_stride = (qpitch / res->block_height) * xfer->base.stride; - } - else { - xfer->base.layer_stride = 0; - } - - x = res->slice_offsets[xfer->base.level][xfer->base.box.z].x; - y = res->slice_offsets[xfer->base.level][xfer->base.box.z].y; - - x += xfer->base.box.x; - y += xfer->base.box.y; - - /* in blocks */ - assert(x % res->block_width == 0 && y % res->block_height == 0); - x /= res->block_width; - y /= res->block_height; - - xfer->ptr = res->bo->get_virtual(res->bo); - xfer->ptr += y * res->bo_stride + x * res->bo_cpp; - - return true; -} - -/** - * Choose the best mapping method, depending on the transfer usage and whether - * the bo is busy. - */ -static bool -transfer_map_choose_method(struct ilo_context *ilo, - struct ilo_resource *res, - struct ilo_transfer *xfer) -{ - bool will_be_busy, will_stall; - - /* need to convert on-the-fly */ - if (res->bo_format != res->base.format && - !(xfer->base.usage & PIPE_TRANSFER_MAP_DIRECTLY)) { - xfer->method = ILO_TRANSFER_MAP_STAGING_SYS; - - return true; - } - - xfer->method = ILO_TRANSFER_MAP_DIRECT; - - /* unsynchronized map does not stall */ - if (xfer->base.usage & PIPE_TRANSFER_UNSYNCHRONIZED) - return true; - - will_be_busy = ilo->cp->bo->references(ilo->cp->bo, res->bo); - if (!will_be_busy) { - /* - * XXX With hardware context support, the bo may be needed by GPU - * without being referenced by ilo->cp->bo. We have to flush - * unconditionally, and that is bad. - */ - if (ilo->cp->hw_ctx) - ilo_cp_flush(ilo->cp); - - if (!intel_bo_is_busy(res->bo)) - return true; - } - - /* bo is busy and mapping it will stall */ - will_stall = true; - - if (xfer->base.usage & PIPE_TRANSFER_MAP_DIRECTLY) { - /* nothing we can do */ - } - else if (xfer->base.usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { - /* discard old bo and allocate a new one for mapping */ - if (realloc_bo(res)) - will_stall = false; - } - else if (xfer->base.usage & PIPE_TRANSFER_FLUSH_EXPLICIT) { - /* - * We could allocate and return a system buffer here. When a region of - * the buffer is explicitly flushed, we pwrite() the region to a - * temporary bo and emit pipelined copy blit. - * - * For now, do nothing. - */ - } - else if (xfer->base.usage & PIPE_TRANSFER_DISCARD_RANGE) { - /* - * We could allocate a temporary bo for mapping, and emit pipelined copy - * blit upon unmapping. - * - * For now, do nothing. - */ - } - - if (will_stall) { - if (xfer->base.usage & PIPE_TRANSFER_DONTBLOCK) - return false; - - /* flush to make bo busy (so that map() stalls as it should be) */ - if (will_be_busy) - ilo_cp_flush(ilo->cp); - } - - return true; -} - -static void -ilo_transfer_flush_region(struct pipe_context *pipe, - struct pipe_transfer *transfer, - const struct pipe_box *box) -{ -} - -static void -ilo_transfer_unmap(struct pipe_context *pipe, - struct pipe_transfer *transfer) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_resource *res = ilo_resource(transfer->resource); - struct ilo_transfer *xfer = ilo_transfer(transfer); - - switch (xfer->method) { - case ILO_TRANSFER_MAP_DIRECT: - transfer_unmap_direct(ilo, res, xfer); - break; - case ILO_TRANSFER_MAP_STAGING_SYS: - transfer_unmap_sys(ilo, res, xfer); - break; - default: - assert(!"unknown mapping method"); - break; - } - - pipe_resource_reference(&xfer->base.resource, NULL); - FREE(xfer); -} - -static void * -ilo_transfer_map(struct pipe_context *pipe, - struct pipe_resource *r, - unsigned level, - unsigned usage, - const struct pipe_box *box, - struct pipe_transfer **transfer) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_resource *res = ilo_resource(r); - struct ilo_transfer *xfer; - int ok; - - xfer = MALLOC_STRUCT(ilo_transfer); - if (!xfer) { - *transfer = NULL; - return NULL; - } - - xfer->base.resource = NULL; - pipe_resource_reference(&xfer->base.resource, &res->base); - xfer->base.level = level; - xfer->base.usage = usage; - xfer->base.box = *box; - - ok = transfer_map_choose_method(ilo, res, xfer); - if (ok) { - switch (xfer->method) { - case ILO_TRANSFER_MAP_DIRECT: - ok = transfer_map_direct(ilo, res, xfer); - break; - case ILO_TRANSFER_MAP_STAGING_SYS: - ok = transfer_map_sys(ilo, res, xfer); - break; - default: - assert(!"unknown mapping method"); - ok = false; - break; - } - } - - if (!ok) { - pipe_resource_reference(&xfer->base.resource, NULL); - FREE(xfer); - - *transfer = NULL; - - return NULL; - } - - *transfer = &xfer->base; - - return xfer->ptr; -} - static bool alloc_slice_offsets(struct ilo_resource *res) { @@ -1373,7 +941,7 @@ create_resource(struct pipe_screen *screen, else init_texture(res); - if (!realloc_bo(res)) { + if (!ilo_resource_alloc_bo(res)) { free_slice_offsets(res); FREE(res); return NULL; @@ -1449,18 +1017,6 @@ ilo_init_resource_functions(struct ilo_screen *is) } /** - * Initialize transfer-related functions. - */ -void -ilo_init_transfer_functions(struct ilo_context *ilo) -{ - ilo->base.transfer_map = ilo_transfer_map; - ilo->base.transfer_flush_region = ilo_transfer_flush_region; - ilo->base.transfer_unmap = ilo_transfer_unmap; - ilo->base.transfer_inline_write = ilo_transfer_inline_write; -} - -/** * Return the offset (in bytes) to a slice within the bo. * * When tile_aligned is true, the offset is to the tile containing the start |