diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2019-01-29 11:52:33 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2019-01-29 11:52:33 +0000 |
commit | 37bbf6a1792773f11c15a4da1588a7520ee2fb4e (patch) | |
tree | 64944d4aa665a1e479cfc004e446593062254550 /lib/mesa/src/gallium/drivers/vc4/vc4_resource.c | |
parent | 6b139c2063623e9310025247cd966490b9aa57ea (diff) |
Merge Mesa 18.3.2
Diffstat (limited to 'lib/mesa/src/gallium/drivers/vc4/vc4_resource.c')
-rw-r--r-- | lib/mesa/src/gallium/drivers/vc4/vc4_resource.c | 266 |
1 files changed, 103 insertions, 163 deletions
diff --git a/lib/mesa/src/gallium/drivers/vc4/vc4_resource.c b/lib/mesa/src/gallium/drivers/vc4/vc4_resource.c index cdcbcc917..41e6ec5c1 100644 --- a/lib/mesa/src/gallium/drivers/vc4/vc4_resource.c +++ b/lib/mesa/src/gallium/drivers/vc4/vc4_resource.c @@ -22,11 +22,13 @@ * IN THE SOFTWARE. */ +#include "pipe/p_defines.h" #include "util/u_blit.h" #include "util/u_memory.h" #include "util/u_format.h" #include "util/u_inlines.h" #include "util/u_surface.h" +#include "util/u_transfer_helper.h" #include "util/u_upload_mgr.h" #include "drm_fourcc.h" @@ -36,10 +38,6 @@ #include "vc4_resource.h" #include "vc4_tiling.h" -#ifndef DRM_FORMAT_MOD_INVALID -#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) -#endif - static bool vc4_resource_bo_alloc(struct vc4_resource *rsc) { @@ -79,15 +77,8 @@ vc4_resource_transfer_unmap(struct pipe_context *pctx, struct vc4_transfer *trans = vc4_transfer(ptrans); if (trans->map) { - struct vc4_resource *rsc; - struct vc4_resource_slice *slice; - if (trans->ss_resource) { - rsc = vc4_resource(trans->ss_resource); - slice = &rsc->slices[0]; - } else { - rsc = vc4_resource(ptrans->resource); - slice = &rsc->slices[ptrans->level]; - } + struct vc4_resource *rsc = vc4_resource(ptrans->resource); + struct vc4_resource_slice *slice = &rsc->slices[ptrans->level]; if (ptrans->usage & PIPE_TRANSFER_WRITE) { vc4_store_tiled_image(rsc->bo->map + slice->offset + @@ -100,51 +91,10 @@ vc4_resource_transfer_unmap(struct pipe_context *pctx, free(trans->map); } - if (trans->ss_resource && (ptrans->usage & PIPE_TRANSFER_WRITE)) { - struct pipe_blit_info blit; - memset(&blit, 0, sizeof(blit)); - - blit.src.resource = trans->ss_resource; - blit.src.format = trans->ss_resource->format; - blit.src.box.width = trans->ss_box.width; - blit.src.box.height = trans->ss_box.height; - blit.src.box.depth = 1; - - blit.dst.resource = ptrans->resource; - blit.dst.format = ptrans->resource->format; - blit.dst.level = ptrans->level; - blit.dst.box = trans->ss_box; - - blit.mask = util_format_get_mask(ptrans->resource->format); - blit.filter = PIPE_TEX_FILTER_NEAREST; - - pctx->blit(pctx, &blit); - - pipe_resource_reference(&trans->ss_resource, NULL); - } - pipe_resource_reference(&ptrans->resource, NULL); slab_free(&vc4->transfer_pool, ptrans); } -static struct pipe_resource * -vc4_get_temp_resource(struct pipe_context *pctx, - struct pipe_resource *prsc, - const struct pipe_box *box) -{ - struct pipe_resource temp_setup; - - memset(&temp_setup, 0, sizeof(temp_setup)); - temp_setup.target = prsc->target; - temp_setup.format = prsc->format; - temp_setup.width0 = box->width; - temp_setup.height0 = box->height; - temp_setup.depth0 = 1; - temp_setup.array_size = 1; - - return pctx->screen->resource_create(pctx->screen, &temp_setup); -} - static void * vc4_resource_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, @@ -164,7 +114,7 @@ vc4_resource_transfer_map(struct pipe_context *pctx, */ if ((usage & PIPE_TRANSFER_DISCARD_RANGE) && !(usage & PIPE_TRANSFER_UNSYNCHRONIZED) && - !(prsc->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT) && + !(prsc->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) && prsc->last_level == 0 && prsc->width0 == box->width && prsc->height0 == box->height && @@ -218,50 +168,6 @@ vc4_resource_transfer_map(struct pipe_context *pctx, ptrans->usage = usage; ptrans->box = *box; - /* If the resource is multisampled, we need to resolve to single - * sample. This seems like it should be handled at a higher layer. - */ - if (prsc->nr_samples > 1) { - trans->ss_resource = vc4_get_temp_resource(pctx, prsc, box); - if (!trans->ss_resource) - goto fail; - assert(!trans->ss_resource->nr_samples); - - /* The ptrans->box gets modified for tile alignment, so save - * the original box for unmap time. - */ - trans->ss_box = *box; - - if (usage & PIPE_TRANSFER_READ) { - struct pipe_blit_info blit; - memset(&blit, 0, sizeof(blit)); - - blit.src.resource = ptrans->resource; - blit.src.format = ptrans->resource->format; - blit.src.level = ptrans->level; - blit.src.box = trans->ss_box; - - blit.dst.resource = trans->ss_resource; - blit.dst.format = trans->ss_resource->format; - blit.dst.box.width = trans->ss_box.width; - blit.dst.box.height = trans->ss_box.height; - blit.dst.box.depth = 1; - - blit.mask = util_format_get_mask(prsc->format); - blit.filter = PIPE_TEX_FILTER_NEAREST; - - pctx->blit(pctx, &blit); - vc4_flush_jobs_writing_resource(vc4, blit.dst.resource); - } - - /* The rest of the mapping process should use our temporary. */ - prsc = trans->ss_resource; - rsc = vc4_resource(prsc); - ptrans->box.x = 0; - ptrans->box.y = 0; - ptrans->box.z = 0; - } - if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) buf = vc4_bo_map_unsynchronized(rsc->bo); else @@ -275,9 +181,6 @@ vc4_resource_transfer_map(struct pipe_context *pctx, struct vc4_resource_slice *slice = &rsc->slices[level]; 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. */ @@ -298,49 +201,12 @@ vc4_resource_transfer_map(struct pipe_context *pctx, ptrans->box.height = (ptrans->box.height + 3) >> 2; } - /* We need to align the box to utile boundaries, since that's - * what load/store operates on. This may cause us to need to - * read out the original contents in that border area. Right - * now we just read out the entire contents, including the - * middle area that will just get overwritten. - */ - uint32_t box_start_x = ptrans->box.x & (utile_w - 1); - uint32_t box_start_y = ptrans->box.y & (utile_h - 1); - bool needs_load = (usage & PIPE_TRANSFER_READ) != 0; - - if (box_start_x) { - ptrans->box.width += box_start_x; - ptrans->box.x -= box_start_x; - needs_load = true; - } - if (box_start_y) { - ptrans->box.height += box_start_y; - ptrans->box.y -= box_start_y; - needs_load = true; - } - if (ptrans->box.width & (utile_w - 1)) { - /* We only need to force a load if our border region - * we're extending into is actually part of the - * texture. - */ - uint32_t slice_width = u_minify(prsc->width0, level); - if (ptrans->box.x + ptrans->box.width != slice_width) - needs_load = true; - ptrans->box.width = align(ptrans->box.width, utile_w); - } - if (ptrans->box.height & (utile_h - 1)) { - uint32_t slice_height = u_minify(prsc->height0, level); - if (ptrans->box.y + ptrans->box.height != slice_height) - needs_load = true; - ptrans->box.height = align(ptrans->box.height, utile_h); - } - ptrans->stride = ptrans->box.width * rsc->cpp; ptrans->layer_stride = ptrans->stride * ptrans->box.height; trans->map = malloc(ptrans->layer_stride * ptrans->box.depth); - if (needs_load) { + if (usage & PIPE_TRANSFER_READ) { vc4_load_tiled_image(trans->map, ptrans->stride, buf + slice->offset + ptrans->box.z * rsc->cube_map_stride, @@ -348,9 +214,7 @@ vc4_resource_transfer_map(struct pipe_context *pctx, slice->tiling, rsc->cpp, &ptrans->box); } - return (trans->map + - box_start_x * rsc->cpp + - box_start_y * ptrans->stride); + return trans->map; } else { ptrans->stride = slice->stride; ptrans->layer_stride = ptrans->stride; @@ -368,6 +232,44 @@ fail: } static void +vc4_texture_subdata(struct pipe_context *pctx, + struct pipe_resource *prsc, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) +{ + struct vc4_resource *rsc = vc4_resource(prsc); + struct vc4_resource_slice *slice = &rsc->slices[level]; + + /* For a direct mapping, we can just take the u_transfer path. */ + if (!rsc->tiled || + box->depth != 1 || + (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE)) { + return u_default_texture_subdata(pctx, prsc, level, usage, box, + data, stride, layer_stride); + } + + /* Otherwise, map and store the texture data directly into the tiled + * texture. + */ + void *buf; + if (usage & PIPE_TRANSFER_UNSYNCHRONIZED) + buf = vc4_bo_map_unsynchronized(rsc->bo); + else + buf = vc4_bo_map(rsc->bo); + + vc4_store_tiled_image(buf + slice->offset + + box->z * rsc->cube_map_stride, + slice->stride, + (void *)data, stride, + slice->tiling, rsc->cpp, + box); +} + +static void vc4_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc) { @@ -406,7 +308,7 @@ vc4_resource_get_handle(struct pipe_screen *pscreen, whandle->modifier = DRM_FORMAT_MOD_LINEAR; switch (whandle->type) { - case DRM_API_HANDLE_TYPE_SHARED: + case WINSYS_HANDLE_TYPE_SHARED: if (screen->ro) { /* This could probably be supported, assuming that a * control node was used for pl111. @@ -416,12 +318,12 @@ vc4_resource_get_handle(struct pipe_screen *pscreen, } return vc4_bo_flink(rsc->bo, &whandle->handle); - case DRM_API_HANDLE_TYPE_KMS: + case WINSYS_HANDLE_TYPE_KMS: if (screen->ro && renderonly_get_handle(rsc->scanout, whandle)) return TRUE; whandle->handle = rsc->bo->handle; return TRUE; - case DRM_API_HANDLE_TYPE_FD: + case WINSYS_HANDLE_TYPE_FD: /* FDs are cross-device, so we can export directly from vc4. */ whandle->handle = vc4_bo_get_dmabuf(rsc->bo); @@ -564,8 +466,10 @@ get_resource_texture_format(struct pipe_resource *prsc) if (prsc->nr_samples > 1) { return ~0; } else { - assert(format == VC4_TEXTURE_TYPE_RGBA8888); - return VC4_TEXTURE_TYPE_RGBA32R; + if (format == VC4_TEXTURE_TYPE_RGBA8888) + return VC4_TEXTURE_TYPE_RGBA32R; + else + return ~0; } } @@ -668,7 +572,15 @@ vc4_resource_create_with_modifiers(struct pipe_screen *pscreen, goto fail; } - if (screen->ro && tmpl->bind & PIPE_BIND_SCANOUT) { + /* Set up the "scanout resource" (the dmabuf export of our buffer to + * the KMS handle) if the buffer might ever have + * resource_get_handle(WINSYS_HANDLE_TYPE_KMS) called on it. + * create_with_modifiers() doesn't give us usage flags, so we have to + * assume that all calls with modifiers are scanout-possible. + */ + if (screen->ro && + ((tmpl->bind & PIPE_BIND_SCANOUT) || + !(count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID))) { rsc->scanout = renderonly_scanout_for_resource(prsc, screen->ro, NULL); if (!rsc->scanout) @@ -708,19 +620,12 @@ vc4_resource_from_handle(struct pipe_screen *pscreen, if (!rsc) return NULL; - if (whandle->offset != 0) { - fprintf(stderr, - "Attempt to import unsupported winsys offset %u\n", - whandle->offset); - return NULL; - } - switch (whandle->type) { - case DRM_API_HANDLE_TYPE_SHARED: + case WINSYS_HANDLE_TYPE_SHARED: rsc->bo = vc4_bo_open_name(screen, whandle->handle, whandle->stride); break; - case DRM_API_HANDLE_TYPE_FD: + case WINSYS_HANDLE_TYPE_FD: rsc->bo = vc4_bo_open_dmabuf(screen, whandle->handle, whandle->stride); break; @@ -766,6 +671,28 @@ vc4_resource_from_handle(struct pipe_screen *pscreen, rsc->vc4_format = get_resource_texture_format(prsc); vc4_setup_slices(rsc, "import"); + if (whandle->offset != 0) { + if (rsc->tiled) { + fprintf(stderr, + "Attempt to import unsupported " + "winsys offset %u\n", + whandle->offset); + goto fail; + } + + rsc->slices[0].offset += whandle->offset; + + if (rsc->slices[0].offset + rsc->slices[0].size > + rsc->bo->size) { + fprintf(stderr, "Attempt to import " + "with overflowing offset (%d + %d > %d)\n", + whandle->offset, + rsc->slices[0].size, + rsc->bo->size); + goto fail; + } + } + if (screen->ro) { /* Make sure that renderonly has a handle to our buffer in the * display's fd, so that a later renderonly_get_handle() @@ -779,7 +706,7 @@ vc4_resource_from_handle(struct pipe_screen *pscreen, goto fail; } - if (whandle->stride != slice->stride) { + if (rsc->tiled && whandle->stride != slice->stride) { static bool warned = false; if (!warned) { warned = true; @@ -792,6 +719,8 @@ vc4_resource_from_handle(struct pipe_screen *pscreen, slice->stride); } goto fail; + } else if (!rsc->tiled) { + slice->stride = whandle->stride; } return prsc; @@ -1187,6 +1116,14 @@ vc4_get_shadow_index_buffer(struct pipe_context *pctx, return shadow_rsc; } +static const struct u_transfer_vtbl transfer_vtbl = { + .resource_create = vc4_resource_create, + .resource_destroy = vc4_resource_destroy, + .transfer_map = vc4_resource_transfer_map, + .transfer_unmap = vc4_resource_transfer_unmap, + .transfer_flush_region = u_default_transfer_flush_region, +}; + void vc4_resource_screen_init(struct pipe_screen *pscreen) { @@ -1199,6 +1136,9 @@ vc4_resource_screen_init(struct pipe_screen *pscreen) pscreen->resource_destroy = u_resource_destroy_vtbl; pscreen->resource_get_handle = vc4_resource_get_handle; pscreen->resource_destroy = vc4_resource_destroy; + pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, + false, false, + false, true); /* Test if the kernel has GET_TILING; it will return -EINVAL if the * ioctl does not exist, but -ENOENT if we pass an impossible handle. @@ -1215,11 +1155,11 @@ vc4_resource_screen_init(struct pipe_screen *pscreen) void vc4_resource_context_init(struct pipe_context *pctx) { - pctx->transfer_map = vc4_resource_transfer_map; - pctx->transfer_flush_region = u_default_transfer_flush_region; - pctx->transfer_unmap = vc4_resource_transfer_unmap; + pctx->transfer_map = u_transfer_helper_transfer_map; + pctx->transfer_flush_region = u_transfer_helper_transfer_flush_region; + pctx->transfer_unmap = u_transfer_helper_transfer_unmap; pctx->buffer_subdata = u_default_buffer_subdata; - pctx->texture_subdata = u_default_texture_subdata; + pctx->texture_subdata = vc4_texture_subdata; pctx->create_surface = vc4_create_surface; pctx->surface_destroy = vc4_surface_destroy; pctx->resource_copy_region = util_resource_copy_region; |