diff options
author | Eric Anholt <[email protected]> | 2014-08-19 09:40:37 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2014-08-22 10:16:57 -0700 |
commit | 3a1efcc7f9f99d42cda191ded1eb78140366c708 (patch) | |
tree | facf7091502e68b2da35810513efbcea765c4916 /src/gallium/drivers/vc4/vc4_resource.c | |
parent | 1b6dcaf40c639d7933e83fecfdf28dbe84175ac6 (diff) |
vc4: Add support for texture tiling.
This still treats everything as RGBA8888 for the most part, same as
before. This is a prerequisite for handling other texture formats, since
only RGBA8888 has a raster-layout mode.
Diffstat (limited to 'src/gallium/drivers/vc4/vc4_resource.c')
-rw-r--r-- | src/gallium/drivers/vc4/vc4_resource.c | 137 |
1 files changed, 125 insertions, 12 deletions
diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c index c2978c0433a..fb46be3916b 100644 --- a/src/gallium/drivers/vc4/vc4_resource.c +++ b/src/gallium/drivers/vc4/vc4_resource.c @@ -31,12 +31,28 @@ #include "vc4_screen.h" #include "vc4_context.h" #include "vc4_resource.h" +#include "vc4_tiling.h" static void vc4_resource_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) { struct vc4_context *vc4 = vc4_context(pctx); + struct vc4_transfer *trans = vc4_transfer(ptrans); + struct pipe_resource *prsc = ptrans->resource; + struct vc4_resource *rsc = vc4_resource(prsc); + struct vc4_resource_slice *slice = &rsc->slices[ptrans->level]; + + if (trans->map) { + if (ptrans->usage & PIPE_TRANSFER_WRITE) { + vc4_store_tiled_image(rsc->bo->map + slice->offset, + slice->stride, + trans->map, ptrans->stride, + slice->tiling, rsc->cpp, + &ptrans->box); + } + free(trans->map); + } pipe_resource_reference(&ptrans->resource, NULL); util_slab_free(&vc4->transfer_pool, ptrans); @@ -51,25 +67,30 @@ vc4_resource_transfer_map(struct pipe_context *pctx, { struct vc4_context *vc4 = vc4_context(pctx); struct vc4_resource *rsc = vc4_resource(prsc); + struct vc4_resource_slice *slice = &rsc->slices[level]; + struct vc4_transfer *trans; struct pipe_transfer *ptrans; enum pipe_format format = prsc->format; char *buf; vc4_flush_for_bo(pctx, rsc->bo); - ptrans = util_slab_alloc(&vc4->transfer_pool); - if (!ptrans) + trans = util_slab_alloc(&vc4->transfer_pool); + if (!trans) return NULL; + /* XXX: Handle DISCARD_WHOLE_RESOURCE, DONTBLOCK, UNSYNCHRONIZED, + * DISCARD_WHOLE_RESOURCE, PERSISTENT, COHERENT. + */ + /* util_slab_alloc() doesn't zero: */ - memset(ptrans, 0, sizeof(*ptrans)); + memset(trans, 0, sizeof(*trans)); + ptrans = &trans->base; pipe_resource_reference(&ptrans->resource, prsc); ptrans->level = level; ptrans->usage = usage; ptrans->box = *box; - ptrans->stride = rsc->slices[level].stride; - ptrans->layer_stride = ptrans->stride; /* Note that the current kernel implementation is synchronous, so no * need to do syncing stuff here yet. @@ -83,10 +104,52 @@ vc4_resource_transfer_map(struct pipe_context *pctx, *pptrans = ptrans; - return buf + rsc->slices[level].offset + - box->y / util_format_get_blockheight(format) * ptrans->stride + - box->x / util_format_get_blockwidth(format) * rsc->cpp + - box->z * rsc->slices[level].size0; + if (rsc->tiled) { + uint32_t utile_w = vc4_utile_width(rsc->cpp); + uint32_t utile_h = vc4_utile_height(rsc->cpp); + + /* No direct mappings of tiled, since we need to manually + * tile/untile. + */ + if (usage & PIPE_TRANSFER_MAP_DIRECTLY) + return NULL; + + /* We need to align the box to utile boundaries, since that's + * what load/store operate on. + */ + uint32_t box_start_x = ptrans->box.x & (utile_w - 1); + uint32_t box_start_y = ptrans->box.y & (utile_h - 1); + ptrans->box.width += box_start_x; + ptrans->box.x -= box_start_x; + ptrans->box.height += box_start_y; + ptrans->box.y -= box_start_y; + ptrans->box.width = align(ptrans->box.width, utile_w); + ptrans->box.height = align(ptrans->box.height, utile_h); + + ptrans->stride = ptrans->box.width * rsc->cpp; + ptrans->layer_stride = ptrans->stride; + + trans->map = malloc(ptrans->stride * ptrans->box.height); + if (usage & PIPE_TRANSFER_READ) { + vc4_load_tiled_image(trans->map, ptrans->stride, + buf + slice->offset, + slice->stride, + slice->tiling, rsc->cpp, + &ptrans->box); + } + return (trans->map + + box_start_x * rsc->cpp + + box_start_y * ptrans->stride); + } else { + ptrans->stride = slice->stride; + ptrans->layer_stride = ptrans->stride; + + return buf + slice->offset + + box->y / util_format_get_blockheight(format) * ptrans->stride + + box->x / util_format_get_blockwidth(format) * rsc->cpp + + box->z * slice->size0; + } + fail: vc4_resource_transfer_unmap(pctx, ptrans); @@ -130,14 +193,34 @@ vc4_setup_slices(struct vc4_resource *rsc) uint32_t height = prsc->height0; uint32_t depth = prsc->depth0; uint32_t offset = 0; + uint32_t utile_w = vc4_utile_width(rsc->cpp); + uint32_t utile_h = vc4_utile_height(rsc->cpp); for (int i = prsc->last_level; i >= 0; i--) { struct vc4_resource_slice *slice = &rsc->slices[i]; uint32_t level_width = u_minify(width, i); uint32_t level_height = u_minify(height, i); + if (rsc->tiled == VC4_TILING_FORMAT_LINEAR) { + slice->tiling = VC4_TILING_FORMAT_LINEAR; + level_width = align(level_width, 16); + } else { + if (vc4_size_is_lt(level_width, level_height, + rsc->cpp)) { + slice->tiling = VC4_TILING_FORMAT_LT; + level_width = align(level_width, utile_w); + level_height = align(level_height, utile_h); + } else { + slice->tiling = VC4_TILING_FORMAT_T; + level_width = align(level_width, + 4 * 2 * utile_w); + level_height = align(level_height, + 4 * 2 * utile_h); + } + } + slice->offset = offset; - slice->stride = align(level_width * rsc->cpp, 16); + slice->stride = level_width * rsc->cpp; slice->size0 = level_height * slice->stride; /* Note, since we have cubes but no 3D, depth is invariant @@ -180,6 +263,17 @@ vc4_resource_setup(struct pipe_screen *pscreen, return rsc; } +static enum vc4_texture_data_type +get_resource_texture_format(struct pipe_resource *prsc) +{ + struct vc4_resource *rsc = vc4_resource(prsc); + + if (rsc->tiled) + return VC4_TEXTURE_TYPE_RGBA8888; + else + return VC4_TEXTURE_TYPE_RGBA32R; +} + static struct pipe_resource * vc4_resource_create(struct pipe_screen *pscreen, const struct pipe_resource *tmpl) @@ -187,9 +281,21 @@ vc4_resource_create(struct pipe_screen *pscreen, struct vc4_resource *rsc = vc4_resource_setup(pscreen, tmpl); struct pipe_resource *prsc = &rsc->base.b; + /* We have to make shared be untiled, since we don't have any way to + * communicate metadata about tiling currently. + */ + if (tmpl->target == PIPE_BUFFER || + (tmpl->bind & (PIPE_BIND_SCANOUT | + PIPE_BIND_LINEAR | + PIPE_BIND_SHARED | + PIPE_BIND_CURSOR))) { + rsc->tiled = false; + } else { + rsc->tiled = true; + } + vc4_setup_slices(rsc); - rsc->tiling = VC4_TILING_FORMAT_LINEAR; rsc->bo = vc4_bo_alloc(vc4_screen(pscreen), rsc->slices[0].offset + rsc->slices[0].size0 * prsc->depth0, @@ -197,6 +303,9 @@ vc4_resource_create(struct pipe_screen *pscreen, if (!rsc->bo) goto fail; + if (tmpl->target != PIPE_BUFFER) + rsc->vc4_format = get_resource_texture_format(prsc); + return prsc; fail: vc4_resource_destroy(pscreen, prsc); @@ -215,7 +324,7 @@ vc4_resource_from_handle(struct pipe_screen *pscreen, if (!rsc) return NULL; - rsc->tiling = VC4_TILING_FORMAT_LINEAR; + rsc->tiled = false; rsc->bo = vc4_screen_bo_from_handle(pscreen, handle, &slice->stride); if (!rsc->bo) goto fail; @@ -223,6 +332,9 @@ vc4_resource_from_handle(struct pipe_screen *pscreen, #ifdef USE_VC4_SIMULATOR slice->stride = align(prsc->width0 * rsc->cpp, 16); #endif + slice->tiling = VC4_TILING_FORMAT_LINEAR; + + rsc->vc4_format = get_resource_texture_format(prsc); return prsc; @@ -258,6 +370,7 @@ vc4_create_surface(struct pipe_context *pctx, psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer; psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer; surface->offset = rsc->slices[level].offset; + surface->tiling = rsc->slices[level].tiling; return &surface->base; } |