[PATCH 10/11] etnaviv: implement resource creation with modifier
Lucas Stach
l.stach at pengutronix.de
Fri Jun 23 15:50:27 UTC 2017
This allows to create buffers with a specific tiling layout, which is primarily
used by GBM to allocate the EGL back buffers with the correct tiling/modifier
for use with the scanout engines.
Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
---
src/gallium/drivers/etnaviv/etnaviv_resource.c | 97 ++++++++++++++++++++++++--
src/gallium/drivers/etnaviv/etnaviv_resource.h | 2 +-
src/gallium/drivers/etnaviv/etnaviv_texture.c | 2 +-
src/gallium/drivers/etnaviv/etnaviv_transfer.c | 2 +-
4 files changed, 96 insertions(+), 7 deletions(-)
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index df5a5700bc19..8462012b9d5f 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -161,7 +161,7 @@ setup_miptree(struct etna_resource *rsc, unsigned paddingX, unsigned paddingY,
/* Create a new resource object, using the given template info */
struct pipe_resource *
etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
- const struct pipe_resource *templat)
+ uint64_t modifier, const struct pipe_resource *templat)
{
struct etna_screen *screen = etna_screen(pscreen);
struct etna_resource *rsc;
@@ -217,8 +217,13 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
unsigned padX, padY;
/* pad scanout buffer size to be compatible with the RS */
- padX = ETNA_RS_WIDTH_MASK + 1;
- padY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes;
+ if (modifier != DRM_FORMAT_MOD_LINEAR) {
+ padX = paddingX;
+ padY = paddingY;
+ } else {
+ padX = ETNA_RS_WIDTH_MASK + 1;
+ padY = (ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes;
+ }
scanout_templat.width0 = align(scanout_templat.width0, padX);
scanout_templat.height0 = align(scanout_templat.height0, padY);
@@ -227,6 +232,7 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
if (!scanout)
return NULL;
+ handle.modifier = modifier;
rsc = etna_resource(pscreen->resource_from_handle(pscreen, templat,
&handle,
PIPE_HANDLE_USAGE_WRITE));
@@ -331,7 +337,89 @@ etna_resource_create(struct pipe_screen *pscreen,
if (templat->target == PIPE_TEXTURE_3D)
layout = ETNA_LAYOUT_LINEAR;
- return etna_resource_alloc(pscreen, layout, templat);
+ /* modifier is only used for scanout surfaces, so safe to use LINEAR here */
+ return etna_resource_alloc(pscreen, layout, DRM_FORMAT_MOD_LINEAR, templat);
+}
+
+enum modifier_priority {
+ MODIFIER_PRIORITY_INVALID = 0,
+ MODIFIER_PRIORITY_LINEAR,
+ MODIFIER_PRIORITY_SPLIT_TILED,
+ MODIFIER_PRIORITY_SPLIT_SUPER_TILED,
+ MODIFIER_PRIORITY_TILED,
+ MODIFIER_PRIORITY_SUPER_TILED,
+};
+
+const uint64_t priority_to_modifier[] = {
+ [MODIFIER_PRIORITY_INVALID] = DRM_FORMAT_MOD_INVALID,
+ [MODIFIER_PRIORITY_LINEAR] = DRM_FORMAT_MOD_LINEAR,
+ [MODIFIER_PRIORITY_SPLIT_TILED] = DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED,
+ [MODIFIER_PRIORITY_SPLIT_SUPER_TILED] = DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED,
+ [MODIFIER_PRIORITY_TILED] = DRM_FORMAT_MOD_VIVANTE_TILED,
+ [MODIFIER_PRIORITY_SUPER_TILED] = DRM_FORMAT_MOD_VIVANTE_SUPER_TILED,
+};
+
+static uint64_t
+select_best_modifier(const struct etna_screen * screen,
+ const uint64_t *modifiers, const unsigned count)
+{
+ enum modifier_priority prio = MODIFIER_PRIORITY_INVALID;
+
+ for (int i = 0; i < count; i++) {
+ switch (modifiers[i]) {
+ case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED:
+ if ((screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer) ||
+ !screen->specs.can_supertile)
+ break;
+ prio = MAX2(prio, MODIFIER_PRIORITY_SUPER_TILED);
+ break;
+ case DRM_FORMAT_MOD_VIVANTE_TILED:
+ if (screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer)
+ break;
+ prio = MAX2(prio, MODIFIER_PRIORITY_TILED);
+ break;
+ case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED:
+ if ((screen->specs.pixel_pipes < 2) || !screen->specs.can_supertile)
+ break;
+ prio = MAX2(prio, MODIFIER_PRIORITY_SPLIT_SUPER_TILED);
+ break;
+ case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED:
+ if (screen->specs.pixel_pipes < 2)
+ break;
+ prio = MAX2(prio, MODIFIER_PRIORITY_SPLIT_TILED);
+ break;
+ case DRM_FORMAT_MOD_LINEAR:
+ prio = MAX2(prio, MODIFIER_PRIORITY_LINEAR);
+ break;
+ case DRM_FORMAT_MOD_INVALID:
+ default:
+ break;
+ }
+ }
+
+ return priority_to_modifier[prio];
+}
+
+static struct pipe_resource *
+etna_resource_create_modifiers(struct pipe_screen *pscreen,
+ const struct pipe_resource *templat,
+ const uint64_t *modifiers, int count)
+{
+ struct etna_screen *screen = etna_screen(pscreen);
+ struct pipe_resource tmpl = *templat;
+ uint64_t modifier = select_best_modifier(screen, modifiers, count);
+
+ if (modifier == DRM_FORMAT_MOD_INVALID)
+ return NULL;
+
+ /*
+ * We currently assume that all buffers allocated through this interface
+ * should be scanout enabled.
+ */
+ tmpl.bind |= PIPE_BIND_SCANOUT;
+
+ return etna_resource_alloc(pscreen, modifier_to_layout(modifier),
+ modifier, &tmpl);
}
static void
@@ -543,6 +631,7 @@ etna_resource_screen_init(struct pipe_screen *pscreen)
{
pscreen->can_create_resource = etna_screen_can_create_resource;
pscreen->resource_create = etna_resource_create;
+ pscreen->resource_create_with_modifiers = etna_resource_create_modifiers;
pscreen->resource_from_handle = etna_resource_from_handle;
pscreen->resource_get_handle = etna_resource_get_handle;
pscreen->resource_changed = etna_resource_changed;
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h
index 5f563c06adcf..0b135e2373b6 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
@@ -151,7 +151,7 @@ etna_screen_resource_alloc_ts(struct pipe_screen *pscreen,
struct pipe_resource *
etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
- const struct pipe_resource *templat);
+ uint64_t modifier, const struct pipe_resource *templat);
void
etna_resource_screen_init(struct pipe_screen *pscreen);
diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.c b/src/gallium/drivers/etnaviv/etnaviv_texture.c
index b7e424f89bba..204c31d33b1e 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_texture.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_texture.c
@@ -181,7 +181,7 @@ etna_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
templat.bind &= ~(PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET |
PIPE_BIND_BLENDABLE);
res->texture =
- etna_resource_alloc(pctx->screen, ETNA_LAYOUT_TILED, &templat);
+ etna_resource_alloc(pctx->screen, ETNA_LAYOUT_TILED, 0, &templat);
}
if (!res->texture) {
diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
index 27e1be19579a..3795c7839081 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
@@ -203,7 +203,7 @@ etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc,
templ.nr_samples = 0;
templ.bind = PIPE_BIND_RENDER_TARGET;
- trans->rsc = etna_resource_alloc(pctx->screen, ETNA_LAYOUT_LINEAR, &templ);
+ trans->rsc = etna_resource_alloc(pctx->screen, ETNA_LAYOUT_LINEAR, 0, &templ);
if (!trans->rsc) {
slab_free(&ctx->transfer_pool, trans);
return NULL;
--
2.11.0
More information about the etnaviv
mailing list