On Fri, Jun 23, 2017 at 05:50:27PM +0200, Lucas Stach wrote: > 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.st...@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;
We repeat `4 * screen->specs.pixel_pipes`, or in this case `(ETNA_RS_HEIGHT_MASK + 1) * screen->specs.pixel_pipes` in many places. Maybe this 'minimum padding for RS' computation logic could factored out for more readable code. > + } > 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 > > _______________________________________________ > etnaviv mailing list > etna...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/etnaviv _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev