diff options
author | Lucas Stach <[email protected]> | 2017-06-22 15:14:31 +0200 |
---|---|---|
committer | Lucas Stach <[email protected]> | 2017-07-19 16:26:50 +0200 |
commit | 58c3ce071c28b2d132cb15e309b3168953d957bd (patch) | |
tree | 3e17f70ae68082b36a2b1703f4753a7ba9813bf6 /src/gallium/drivers/etnaviv/etnaviv_resource.c | |
parent | d06cfaf4fc21d45d09045af9ea2a248ef3968767 (diff) |
etnaviv: implement resource creation with modifier
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 <[email protected]>
Reviewed-by: Christian Gmeiner <[email protected]>
Reviewed-by: Daniel Stone <[email protected]>
Diffstat (limited to 'src/gallium/drivers/etnaviv/etnaviv_resource.c')
-rw-r--r-- | src/gallium/drivers/etnaviv/etnaviv_resource.c | 95 |
1 files changed, 91 insertions, 4 deletions
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c index 63ed8bacf0a..d6cccd2dbb1 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c @@ -179,7 +179,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; @@ -231,8 +231,11 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout, struct winsys_handle handle; /* pad scanout buffer size to be compatible with the RS */ - etna_adjust_rs_align(screen->specs.pixel_pipes, - &scanout_templat.width0, &scanout_templat.height0); + if (modifier == DRM_FORMAT_MOD_LINEAR) + etna_adjust_rs_align(screen->specs.pixel_pipes, &paddingX, &paddingY); + + scanout_templat.width0 = align(scanout_templat.width0, paddingX); + scanout_templat.height0 = align(scanout_templat.height0, paddingY); scanout = renderonly_scanout_for_resource(&scanout_templat, screen->ro, &handle); @@ -240,6 +243,7 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout, return NULL; assert(handle.type == DRM_API_HANDLE_TYPE_FD); + handle.modifier = modifier; rsc = etna_resource(pscreen->resource_from_handle(pscreen, templat, &handle, PIPE_HANDLE_USAGE_WRITE)); @@ -344,7 +348,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 @@ -542,6 +628,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; |