summaryrefslogtreecommitdiff
path: root/lib/mesa/src/gallium/drivers/vc4/vc4_resource.c
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2019-01-29 11:52:33 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2019-01-29 11:52:33 +0000
commit37bbf6a1792773f11c15a4da1588a7520ee2fb4e (patch)
tree64944d4aa665a1e479cfc004e446593062254550 /lib/mesa/src/gallium/drivers/vc4/vc4_resource.c
parent6b139c2063623e9310025247cd966490b9aa57ea (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.c266
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;