Rather than hard-code a list of all the format modifiers supported by any gallium driver in the dri state tracker, add a screen proc that queries the number of auxiliary planes required for a given modifier+format pair.
Since the only format modifier that requires auxiliary planes currently is the iris driver's I915_FORMAT_MOD_Y_TILED_CCS, provide a generic implementation of this screen proc as a utility function, and use that in every driver besides the iris driver, which requires a trivial customization on top of it. Signed-off-by: James Jones <jajo...@nvidia.com> --- src/gallium/auxiliary/util/u_screen.c | 35 ++++++++++++++++++ src/gallium/auxiliary/util/u_screen.h | 7 ++++ src/gallium/drivers/etnaviv/etnaviv_screen.c | 1 + .../drivers/freedreno/freedreno_screen.c | 1 + src/gallium/drivers/iris/iris_resource.c | 17 +++++++++ src/gallium/drivers/lima/lima_screen.c | 1 + .../drivers/nouveau/nvc0/nvc0_resource.c | 2 ++ src/gallium/drivers/tegra/tegra_screen.c | 12 +++++++ src/gallium/drivers/v3d/v3d_screen.c | 1 + src/gallium/drivers/vc4/vc4_screen.c | 1 + src/gallium/include/pipe/p_screen.h | 15 ++++++++ src/gallium/state_trackers/dri/dri2.c | 36 ++++++++----------- 12 files changed, 107 insertions(+), 22 deletions(-) diff --git a/src/gallium/auxiliary/util/u_screen.c b/src/gallium/auxiliary/util/u_screen.c index 785d1bd3e24..0697d483372 100644 --- a/src/gallium/auxiliary/util/u_screen.c +++ b/src/gallium/auxiliary/util/u_screen.c @@ -412,3 +412,38 @@ u_pipe_screen_get_param_defaults(struct pipe_screen *pscreen, unreachable("bad PIPE_CAP_*"); } } + +bool +u_pipe_screen_get_modifier_aux_planes(struct pipe_screen *pscreen, + uint64_t modifier, + enum pipe_format format, + unsigned *num_aux_planes) +{ + int num_mods, i; + uint64_t *supported_mods; + + pscreen->query_dmabuf_modifiers(pscreen, format, 0, NULL, NULL, + &num_mods); + + if (!num_mods) + return false; + + supported_mods = malloc(num_mods * sizeof(supported_mods[0])); + + if (!supported_mods) + return false; + + pscreen->query_dmabuf_modifiers(pscreen, format, num_mods, supported_mods, + NULL, &num_mods); + + for (i = 0; i < num_mods && supported_mods[i] != modifier; i++); + + free(supported_mods); + + if (i == num_mods) + return false; + + *num_aux_planes = 0; + + return true; +} diff --git a/src/gallium/auxiliary/util/u_screen.h b/src/gallium/auxiliary/util/u_screen.h index 3952a11f2ca..0abcfd282b1 100644 --- a/src/gallium/auxiliary/util/u_screen.h +++ b/src/gallium/auxiliary/util/u_screen.h @@ -23,6 +23,7 @@ struct pipe_screen; enum pipe_cap; +enum pipe_format; #ifdef __cplusplus extern "C" { @@ -32,6 +33,12 @@ int u_pipe_screen_get_param_defaults(struct pipe_screen *pscreen, enum pipe_cap param); +bool +u_pipe_screen_get_modifier_aux_planes(struct pipe_screen *pscreen, + uint64_t modifier, + enum pipe_format format, + unsigned *num_aux_planes); + #ifdef __cplusplus }; #endif diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c index dcceddc4729..32909a4e5ea 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c @@ -1019,6 +1019,7 @@ etna_screen_create(struct etna_device *dev, struct etna_gpu *gpu, pscreen->context_create = etna_context_create; pscreen->is_format_supported = etna_screen_is_format_supported; pscreen->query_dmabuf_modifiers = etna_screen_query_dmabuf_modifiers; + pscreen->get_modifier_aux_planes = u_pipe_screen_get_modifier_aux_planes; etna_fence_screen_init(pscreen); etna_query_screen_init(pscreen); diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 3c0ed69a9cb..5d25df02ebf 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -984,6 +984,7 @@ fd_screen_create(struct fd_device *dev, struct renderonly *ro) pscreen->fence_get_fd = fd_fence_get_fd; pscreen->query_dmabuf_modifiers = fd_screen_query_dmabuf_modifiers; + pscreen->get_modifier_aux_planes = u_pipe_screen_get_modifier_aux_planes; if (!screen->supported_modifiers) { static const uint64_t supported_modifiers[] = { diff --git a/src/gallium/drivers/iris/iris_resource.c b/src/gallium/drivers/iris/iris_resource.c index bdd715df2c9..a3b0e87070f 100644 --- a/src/gallium/drivers/iris/iris_resource.c +++ b/src/gallium/drivers/iris/iris_resource.c @@ -38,6 +38,7 @@ #include "util/u_cpu_detect.h" #include "util/u_inlines.h" #include "util/format/u_format.h" +#include "util/u_screen.h" #include "util/u_threaded_context.h" #include "util/u_transfer.h" #include "util/u_transfer_helper.h" @@ -193,6 +194,21 @@ iris_query_dmabuf_modifiers(struct pipe_screen *pscreen, *count = supported_mods; } +static bool +iris_get_modifier_aux_planes(struct pipe_screen *pscreen, + uint64_t modifier, + enum pipe_format format, + unsigned *num_aux_planes) +{ + bool ret = u_pipe_screen_get_modifier_aux_planes(pscreen, modifier, format, + num_aux_planes); + + if (ret && modifier == I915_FORMAT_MOD_Y_TILED_CCS) + *num_aux_planes = 1; + + return ret; +} + static isl_surf_usage_flags_t pipe_bind_to_isl_usage(unsigned bindings) { @@ -2075,6 +2091,7 @@ void iris_init_screen_resource_functions(struct pipe_screen *pscreen) { pscreen->query_dmabuf_modifiers = iris_query_dmabuf_modifiers; + pscreen->get_modifier_aux_planes = iris_get_modifier_aux_planes; pscreen->resource_create_with_modifiers = iris_resource_create_with_modifiers; pscreen->resource_create = u_transfer_helper_resource_create; diff --git a/src/gallium/drivers/lima/lima_screen.c b/src/gallium/drivers/lima/lima_screen.c index 0995ac86e6d..19ff3deeda1 100644 --- a/src/gallium/drivers/lima/lima_screen.c +++ b/src/gallium/drivers/lima/lima_screen.c @@ -598,6 +598,7 @@ lima_screen_create(int fd, struct renderonly *ro) screen->base.is_format_supported = lima_screen_is_format_supported; screen->base.get_compiler_options = lima_screen_get_compiler_options; screen->base.query_dmabuf_modifiers = lima_screen_query_dmabuf_modifiers; + screen->base.get_modifier_aux_planes = u_pipe_screen_get_modifier_aux_planes; lima_resource_screen_init(screen); lima_fence_screen_init(screen); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c b/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c index d73ecf71624..ab7bc69022c 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c @@ -3,6 +3,7 @@ #include "pipe/p_context.h" #include "nvc0/nvc0_resource.h" #include "nouveau_screen.h" +#include "util/u_screen.h" static struct pipe_resource * @@ -117,6 +118,7 @@ nvc0_screen_init_resource_functions(struct pipe_screen *pscreen) pscreen->resource_create = nvc0_resource_create; pscreen->resource_create_with_modifiers = nvc0_resource_create_with_modifiers; pscreen->query_dmabuf_modifiers = nvc0_query_dmabuf_modifiers; + pscreen->get_modifier_aux_planes = u_pipe_screen_get_modifier_aux_planes; pscreen->resource_from_handle = nvc0_resource_from_handle; pscreen->resource_get_handle = u_resource_get_handle_vtbl; pscreen->resource_destroy = u_resource_destroy_vtbl; diff --git a/src/gallium/drivers/tegra/tegra_screen.c b/src/gallium/drivers/tegra/tegra_screen.c index 9ec3f6fe1d4..638f9b12797 100644 --- a/src/gallium/drivers/tegra/tegra_screen.c +++ b/src/gallium/drivers/tegra/tegra_screen.c @@ -514,6 +514,17 @@ static void tegra_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen, external_only, count); } +static bool tegra_screen_get_modifier_aux_planes(struct pipe_screen *pscreen, + uint64_t modifier, + enum pipe_format format, + unsigned *num_aux_planes) +{ + struct tegra_screen *screen = to_tegra_screen(pscreen); + + return screen->gpu->get_modifier_aux_planes(screen->gpu, modifier, format, + num_aux_planes); +} + static struct pipe_memory_object * tegra_screen_memobj_create_from_handle(struct pipe_screen *pscreen, struct winsys_handle *handle, @@ -592,6 +603,7 @@ tegra_screen_create(int fd) screen->base.resource_create_with_modifiers = tegra_screen_resource_create_with_modifiers; screen->base.query_dmabuf_modifiers = tegra_screen_query_dmabuf_modifiers; + screen->base.get_modifier_aux_planes = tegra_screen_get_modifier_aux_planes; screen->base.memobj_create_from_handle = tegra_screen_memobj_create_from_handle; return &screen->base; diff --git a/src/gallium/drivers/v3d/v3d_screen.c b/src/gallium/drivers/v3d/v3d_screen.c index 1b0c219cb58..c818edc158c 100644 --- a/src/gallium/drivers/v3d/v3d_screen.c +++ b/src/gallium/drivers/v3d/v3d_screen.c @@ -719,6 +719,7 @@ v3d_screen_create(int fd, const struct pipe_screen_config *config, pscreen->get_device_vendor = v3d_screen_get_vendor; pscreen->get_compiler_options = v3d_screen_get_compiler_options; pscreen->query_dmabuf_modifiers = v3d_screen_query_dmabuf_modifiers; + pscreen->get_modifier_aux_planes = u_pipe_screen_get_modifier_aux_planes; return pscreen; diff --git a/src/gallium/drivers/vc4/vc4_screen.c b/src/gallium/drivers/vc4/vc4_screen.c index 2be0b6c3fbe..8e4d6e24ea6 100644 --- a/src/gallium/drivers/vc4/vc4_screen.c +++ b/src/gallium/drivers/vc4/vc4_screen.c @@ -566,6 +566,7 @@ vc4_screen_create(int fd, struct renderonly *ro) pscreen->get_device_vendor = vc4_screen_get_vendor; pscreen->get_compiler_options = vc4_screen_get_compiler_options; pscreen->query_dmabuf_modifiers = vc4_screen_query_dmabuf_modifiers; + pscreen->get_modifier_aux_planes = u_pipe_screen_get_modifier_aux_planes; if (screen->has_perfmon_ioctl) { pscreen->get_driver_query_group_info = vc4_get_driver_query_group_info; diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h index 0f2831b6eda..596056091c0 100644 --- a/src/gallium/include/pipe/p_screen.h +++ b/src/gallium/include/pipe/p_screen.h @@ -511,6 +511,21 @@ struct pipe_screen { * should be. */ void (*finalize_nir)(struct pipe_screen *screen, void *nir, bool optimize); + + /** + * Get the number of aux planes required for a given modifier/format pair. + * + * If this function returns true, \p num_aux_planes will contain the number + * of additional planes needed (beyond the standard number dictated by + * \p format) to store auxiliary image data for the image layout defined by + * \p modifier. + * + * \return true if the format+modifier pair is supported on \p screen, false + * otherwise. + */ + bool (*get_modifier_aux_planes)(struct pipe_screen *screen, + uint64_t modifier, enum pipe_format format, + unsigned *num_aux_planes); }; diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c index 05ebb4ef1d7..5e688042122 100644 --- a/src/gallium/state_trackers/dri/dri2.c +++ b/src/gallium/state_trackers/dri/dri2.c @@ -839,38 +839,29 @@ dri2_create_image_from_name(__DRIscreen *_screen, } static unsigned -dri2_get_modifier_num_planes(uint64_t modifier, int fourcc) +dri2_get_modifier_num_planes(__DRIscreen *_screen, + uint64_t modifier, int fourcc) { + struct pipe_screen *pscreen = dri_screen(_screen)->base.screen; const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); + unsigned num_aux_planes; if (!map) return 0; switch (modifier) { - case I915_FORMAT_MOD_Y_TILED_CCS: - return 2; - case DRM_FORMAT_MOD_BROADCOM_UIF: - case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: case DRM_FORMAT_MOD_LINEAR: /* DRM_FORMAT_MOD_NONE is the same as LINEAR */ - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB: - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB: - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB: - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB: - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB: - case DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB: - case DRM_FORMAT_MOD_QCOM_COMPRESSED: - case DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED: - case DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED: - case DRM_FORMAT_MOD_VIVANTE_SUPER_TILED: - case DRM_FORMAT_MOD_VIVANTE_TILED: - /* FD_FORMAT_MOD_QCOM_TILED is not in drm_fourcc.h */ - case I915_FORMAT_MOD_X_TILED: - case I915_FORMAT_MOD_Y_TILED: case DRM_FORMAT_MOD_INVALID: return map->nplanes; default: - return 0; + if (!pscreen->get_modifier_aux_planes || + !pscreen->get_modifier_aux_planes(pscreen, modifier, map->pipe_format, + &num_aux_planes)) { + return 0; + } + + return map->nplanes + num_aux_planes; } } @@ -886,7 +877,7 @@ dri2_create_image_from_fd(__DRIscreen *_screen, __DRIimage *img = NULL; unsigned err = __DRI_IMAGE_ERROR_SUCCESS; int i, expected_num_fds; - int num_handles = dri2_get_modifier_num_planes(modifier, fourcc); + int num_handles = dri2_get_modifier_num_planes(_screen, modifier, fourcc); if (!map || num_handles == 0) { err = __DRI_IMAGE_ERROR_BAD_MATCH; @@ -1415,7 +1406,8 @@ dri2_query_dma_buf_format_modifier_attribs(__DRIscreen *_screen, { switch (attrib) { case __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT: { - uint64_t mod_planes = dri2_get_modifier_num_planes(modifier, fourcc); + uint64_t mod_planes = dri2_get_modifier_num_planes(_screen, modifier, + fourcc); if (mod_planes > 0) *value = mod_planes; return mod_planes > 0; -- 2.17.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev