Commit 6ee10ab3 authored by James Jones's avatar James Jones Committed by Marge Bot

gallium: Add pipe_screen::is_dmabuf_modifier_supported

Add a "do you support this modifier?" query to all
drivers which support format modifiers. This will
be used in a subsequent change to fully
encapsulate modifier validation and auxiliary plane
count calculation logic behind the driver
abstraction, which will in turn simplify the
addition of device-class-specific format modifiers
in the nouveau driver.
Signed-off-by: James Jones's avatarJames Jones <jajones@nvidia.com>
Part-of: <!3723>
parent 40e3eb9b
......@@ -1033,6 +1033,17 @@ returned. The callback itself may also be NULL if the driver doesn't support
an on-disk shader cache.
is_dmabuf_modifier_supported
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Query whether the driver supports a **modifier** in combination with a
**format**, and whether it is only supported with "external" texture targets.
If the combination is supported in any fashion, true is returned. If the
**external_only** parameter is not NULL, the bool it points to is set to
false if non-external texture targets are supported with the specified modifier+
format, or true if only external texture targets are supported.
Thread safety
-------------
......
......@@ -165,6 +165,21 @@ rbug_screen_query_dmabuf_modifiers(struct pipe_screen *_screen,
count);
}
static bool
rbug_screen_is_dmabuf_modifier_supported(struct pipe_screen *_screen,
uint64_t modifier,
enum pipe_format format,
bool *external_only)
{
struct rbug_screen *rb_screen = rbug_screen(_screen);
struct pipe_screen *screen = rb_screen->screen;
return screen->is_dmabuf_modifier_supported(screen,
modifier,
format,
external_only);
}
static struct pipe_context *
rbug_screen_context_create(struct pipe_screen *_screen,
void *priv, unsigned flags)
......@@ -427,6 +442,7 @@ rbug_screen_create(struct pipe_screen *screen)
rb_screen->base.get_paramf = rbug_screen_get_paramf;
rb_screen->base.is_format_supported = rbug_screen_is_format_supported;
SCR_INIT(query_dmabuf_modifiers);
SCR_INIT(is_dmabuf_modifier_supported);
rb_screen->base.context_create = rbug_screen_context_create;
SCR_INIT(can_create_resource);
rb_screen->base.resource_create = rbug_screen_resource_create;
......
......@@ -578,13 +578,24 @@ const uint64_t supported_modifiers[] = {
DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED,
};
static bool modifier_num_supported(struct pipe_screen *pscreen, int num)
{
struct etna_screen *screen = etna_screen(pscreen);
/* don't advertise split tiled formats on single pipe/buffer GPUs */
if ((screen->specs.pixel_pipes == 1 || screen->specs.single_buffer) &&
num >= 3)
return false;
return true;
}
static void
etna_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
enum pipe_format format, int max,
uint64_t *modifiers,
unsigned int *external_only, int *count)
{
struct etna_screen *screen = etna_screen(pscreen);
int i, num_modifiers = 0;
if (max > ARRAY_SIZE(supported_modifiers))
......@@ -596,9 +607,7 @@ etna_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
}
for (i = 0; num_modifiers < max; i++) {
/* don't advertise split tiled formats on single pipe/buffer GPUs */
if ((screen->specs.pixel_pipes == 1 || screen->specs.single_buffer) &&
i >= 3)
if (!modifier_num_supported(pscreen, i))
break;
if (modifiers)
......@@ -611,6 +620,29 @@ etna_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
*count = num_modifiers;
}
static bool
etna_screen_is_dmabuf_modifier_supported(struct pipe_screen *pscreen,
uint64_t modifier,
enum pipe_format format,
bool *external_only)
{
int i;
for (i = 0; i < ARRAY_SIZE(supported_modifiers); i++) {
if (!modifier_num_supported(pscreen, i))
break;
if (modifier == supported_modifiers[i]) {
if (external_only)
*external_only = util_format_is_yuv(format) ? 1 : 0;
return true;
}
}
return false;
}
static void
etna_determine_uniform_limits(struct etna_screen *screen)
{
......@@ -1047,6 +1079,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->is_dmabuf_modifier_supported = etna_screen_is_dmabuf_modifier_supported;
screen->compiler = etna_compiler_create(etna_screen_get_name(pscreen));
if (!screen->compiler)
......
......@@ -797,6 +797,27 @@ fd_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
*count = num;
}
static bool
fd_screen_is_dmabuf_modifier_supported(struct pipe_screen *pscreen,
uint64_t modifier,
enum pipe_format format,
bool *external_only)
{
struct fd_screen *screen = fd_screen(pscreen);
int i;
for (i = 0; i < screen->num_supported_modifiers; i++) {
if (modifier == screen->supported_modifiers[i]) {
if (external_only)
*external_only = false;
return true;
}
}
return false;
}
struct fd_bo *
fd_screen_bo_from_handle(struct pipe_screen *pscreen,
struct winsys_handle *whandle)
......@@ -1038,6 +1059,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->is_dmabuf_modifier_supported = fd_screen_is_dmabuf_modifier_supported;
pscreen->get_device_uuid = fd_screen_get_device_uuid;
pscreen->get_driver_uuid = fd_screen_get_driver_uuid;
......
......@@ -190,6 +190,19 @@ target_to_isl_surf_dim(enum pipe_texture_target target)
unreachable("invalid texture type");
}
static inline bool is_modifier_external_only(enum pipe_format pfmt,
uint64_t modifier)
{
/* Only allow external usage for the following cases: YUV formats
* and the media-compression modifier. The render engine lacks
* support for rendering to a media-compressed surface if the
* compression ratio is large enough. By requiring external usage
* of media-compressed surfaces, resolves are avoided.
*/
return util_format_is_yuv(pfmt) ||
modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
}
static void
iris_query_dmabuf_modifiers(struct pipe_screen *pscreen,
enum pipe_format pfmt,
......@@ -221,15 +234,8 @@ iris_query_dmabuf_modifiers(struct pipe_screen *pscreen,
modifiers[supported_mods] = all_modifiers[i];
if (external_only) {
/* Only allow external usage for the following cases: YUV formats
* and the media-compression modifier. The render engine lacks
* support for rendering to a media-compressed surface if the
* compression ratio is large enough. By requiring external usage
* of media-compressed surfaces, resolves are avoided.
*/
external_only[supported_mods] =
util_format_is_yuv(pfmt) ||
all_modifiers[i] == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
is_modifier_external_only(pfmt, all_modifiers[i]);
}
}
......@@ -239,6 +245,24 @@ iris_query_dmabuf_modifiers(struct pipe_screen *pscreen,
*count = supported_mods;
}
static bool
iris_is_dmabuf_modifier_supported(struct pipe_screen *pscreen,
uint64_t modifier, enum pipe_format pfmt,
bool *external_only)
{
struct iris_screen *screen = (void *) pscreen;
const struct gen_device_info *devinfo = &screen->devinfo;
if (modifier_is_supported(devinfo, pfmt, modifier)) {
if (external_only)
*external_only = is_modifier_external_only(pfmt, modifier);
return true;
}
return false;
}
enum isl_format
iris_image_view_get_format(struct iris_context *ice,
const struct pipe_image_view *img)
......@@ -2225,6 +2249,7 @@ void
iris_init_screen_resource_functions(struct pipe_screen *pscreen)
{
pscreen->query_dmabuf_modifiers = iris_query_dmabuf_modifiers;
pscreen->is_dmabuf_modifier_supported = iris_is_dmabuf_modifier_supported;
pscreen->resource_create_with_modifiers =
iris_resource_create_with_modifiers;
pscreen->resource_create = u_transfer_helper_resource_create;
......
......@@ -487,6 +487,11 @@ lima_screen_query_info(struct lima_screen *screen)
return true;
}
static const uint64_t lima_available_modifiers[] = {
DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED,
DRM_FORMAT_MOD_LINEAR,
};
static void
lima_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
enum pipe_format format, int max,
......@@ -494,12 +499,7 @@ lima_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
unsigned int *external_only,
int *count)
{
uint64_t available_modifiers[] = {
DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED,
DRM_FORMAT_MOD_LINEAR,
};
int num_modifiers = ARRAY_SIZE(available_modifiers);
int num_modifiers = ARRAY_SIZE(lima_available_modifiers);
if (!modifiers) {
*count = num_modifiers;
......@@ -508,12 +508,30 @@ lima_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
*count = MIN2(max, num_modifiers);
for (int i = 0; i < *count; i++) {
modifiers[i] = available_modifiers[i];
modifiers[i] = lima_available_modifiers[i];
if (external_only)
external_only[i] = false;
}
}
static bool
lima_screen_is_dmabuf_modifier_supported(struct pipe_screen *pscreen,
uint64_t modifier,
enum pipe_format format,
bool *external_only)
{
for (int i = 0; i < ARRAY_SIZE(lima_available_modifiers); i++) {
if (lima_available_modifiers[i] == modifier) {
if (external_only)
*external_only = false;
return true;
}
}
return false;
}
static const struct debug_named_value debug_options[] = {
{ "gp", LIMA_DEBUG_GP,
"print GP shader compiler result of each stage" },
......@@ -676,6 +694,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.is_dmabuf_modifier_supported = lima_screen_is_dmabuf_modifier_supported;
lima_resource_screen_init(screen);
lima_fence_screen_init(screen);
......
......@@ -32,35 +32,36 @@ nvc0_resource_create_with_modifiers(struct pipe_screen *screen,
}
}
static const uint64_t nvc0_supported_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB,
};
static void
nvc0_query_dmabuf_modifiers(struct pipe_screen *screen,
enum pipe_format format, int max,
uint64_t *modifiers, unsigned int *external_only,
int *count)
{
static const uint64_t supported_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB,
};
int i, num = 0;
if (max > ARRAY_SIZE(supported_modifiers))
max = ARRAY_SIZE(supported_modifiers);
if (max > ARRAY_SIZE(nvc0_supported_modifiers))
max = ARRAY_SIZE(nvc0_supported_modifiers);
if (!max) {
max = ARRAY_SIZE(supported_modifiers);
max = ARRAY_SIZE(nvc0_supported_modifiers);
external_only = NULL;
modifiers = NULL;
}
for (i = 0; i < max; i++) {
if (modifiers)
modifiers[num] = supported_modifiers[i];
modifiers[num] = nvc0_supported_modifiers[i];
if (external_only)
external_only[num] = 0;
......@@ -71,6 +72,25 @@ nvc0_query_dmabuf_modifiers(struct pipe_screen *screen,
*count = num;
}
static bool
nvc0_is_dmabuf_modifier_supported(struct pipe_screen *screen,
uint64_t modifier, enum pipe_format format,
bool *external_only)
{
int i;
for (i = 0; i < ARRAY_SIZE(nvc0_supported_modifiers); i++) {
if (nvc0_supported_modifiers[i] == modifier) {
if (external_only)
*external_only = false;
return true;
}
}
return false;
}
static struct pipe_resource *
nvc0_resource_from_handle(struct pipe_screen * screen,
const struct pipe_resource *templ,
......@@ -130,6 +150,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->is_dmabuf_modifier_supported = nvc0_is_dmabuf_modifier_supported;
pscreen->resource_from_handle = nvc0_resource_from_handle;
pscreen->resource_get_handle = u_resource_get_handle_vtbl;
pscreen->resource_destroy = u_resource_destroy_vtbl;
......
......@@ -507,9 +507,9 @@ panfrost_is_format_supported( struct pipe_screen *screen,
* subset of those. */
static void
panfrost_query_dmabuf_modifiers(struct pipe_screen *screen,
panfrost_walk_dmabuf_modifiers(struct pipe_screen *screen,
enum pipe_format format, int max, uint64_t *modifiers, unsigned
int *external_only, int *out_count)
int *external_only, int *out_count, uint64_t test_modifier)
{
/* Query AFBC status */
bool afbc = panfrost_format_supports_afbc(format);
......@@ -531,6 +531,10 @@ panfrost_query_dmabuf_modifiers(struct pipe_screen *screen,
if ((pan_best_modifiers[i] & AFBC_FORMAT_MOD_YTR) && !ytr)
continue;
if (test_modifier != DRM_FORMAT_MOD_INVALID &&
test_modifier != pan_best_modifiers[i])
continue;
count++;
if (max > (int) count) {
......@@ -544,6 +548,33 @@ panfrost_query_dmabuf_modifiers(struct pipe_screen *screen,
*out_count = count;
}
static void
panfrost_query_dmabuf_modifiers(struct pipe_screen *screen,
enum pipe_format format, int max, uint64_t *modifiers, unsigned
int *external_only, int *out_count)
{
panfrost_walk_dmabuf_modifiers(screen, format, max, modifiers,
external_only, out_count, DRM_FORMAT_MOD_INVALID);
}
static bool
panfrost_is_dmabuf_modifier_supported(struct pipe_screen *screen,
uint64_t modifier, enum pipe_format format,
bool *external_only)
{
uint64_t unused;
unsigned int uint_extern_only = 0;
int count;
panfrost_walk_dmabuf_modifiers(screen, format, 1, &unused,
&uint_extern_only, &count, modifier);
if (external_only)
*external_only = uint_extern_only ? true : false;
return count > 0;
}
static int
panfrost_get_compute_param(struct pipe_screen *pscreen, enum pipe_shader_ir ir_type,
enum pipe_compute_cap param, void *ret)
......@@ -755,6 +786,8 @@ panfrost_create_screen(int fd, struct renderonly *ro)
screen->base.get_timestamp = panfrost_get_timestamp;
screen->base.is_format_supported = panfrost_is_format_supported;
screen->base.query_dmabuf_modifiers = panfrost_query_dmabuf_modifiers;
screen->base.is_dmabuf_modifier_supported =
panfrost_is_dmabuf_modifier_supported;
screen->base.context_create = panfrost_create_context;
screen->base.get_compiler_options = panfrost_screen_get_compiler_options;
screen->base.fence_reference = panfrost_fence_reference;
......
......@@ -514,6 +514,18 @@ static void tegra_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
external_only, count);
}
static bool
tegra_screen_is_dmabuf_modifier_supported(struct pipe_screen *pscreen,
uint64_t modifier,
enum pipe_format format,
bool *external_only)
{
struct tegra_screen *screen = to_tegra_screen(pscreen);
return screen->gpu->is_dmabuf_modifier_supported(screen->gpu, modifier,
format, external_only);
}
static struct pipe_memory_object *
tegra_screen_memobj_create_from_handle(struct pipe_screen *pscreen,
struct winsys_handle *handle,
......@@ -592,6 +604,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.is_dmabuf_modifier_supported = tegra_screen_is_dmabuf_modifier_supported;
screen->base.memobj_create_from_handle = tegra_screen_memobj_create_from_handle;
return &screen->base;
......
......@@ -631,6 +631,11 @@ v3d_screen_get_compiler_options(struct pipe_screen *pscreen,
return &v3d_nir_options;
}
static const uint64_t v3d_available_modifiers[] = {
DRM_FORMAT_MOD_BROADCOM_UIF,
DRM_FORMAT_MOD_LINEAR,
};
static void
v3d_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
enum pipe_format format, int max,
......@@ -639,11 +644,7 @@ v3d_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
int *count)
{
int i;
uint64_t available_modifiers[] = {
DRM_FORMAT_MOD_BROADCOM_UIF,
DRM_FORMAT_MOD_LINEAR,
};
int num_modifiers = ARRAY_SIZE(available_modifiers);
int num_modifiers = ARRAY_SIZE(v3d_available_modifiers);
if (!modifiers) {
*count = num_modifiers;
......@@ -652,12 +653,32 @@ v3d_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
*count = MIN2(max, num_modifiers);
for (i = 0; i < *count; i++) {
modifiers[i] = available_modifiers[i];
modifiers[i] = v3d_available_modifiers[i];
if (external_only)
external_only[i] = false;
}
}
static bool
v3d_screen_is_dmabuf_modifier_supported(struct pipe_screen *pscreen,
uint64_t modifier,
enum pipe_format format,
bool *external_only)
{
int i;
for (i = 0; i < ARRAY_SIZE(v3d_available_modifiers); i++) {
if (v3d_available_modifiers[i] == modifier) {
if (external_only)
*external_only = false;
return true;
}
}
return false;
}
struct pipe_screen *
v3d_screen_create(int fd, const struct pipe_screen_config *config,
struct renderonly *ro)
......@@ -722,6 +743,8 @@ 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->is_dmabuf_modifier_supported =
v3d_screen_is_dmabuf_modifier_supported;
return pscreen;
......
......@@ -411,6 +411,30 @@ vc4_screen_is_format_supported(struct pipe_screen *pscreen,
return true;
}
static const uint64_t *vc4_get_modifiers(struct pipe_screen *pscreen, int *num)
{
struct vc4_screen *screen = vc4_screen(pscreen);
static const uint64_t all_modifiers[] = {
DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
DRM_FORMAT_MOD_LINEAR,
};
int m;
/* We support both modifiers (tiled and linear) for all sampler
* formats, but if we don't have the DRM_VC4_GET_TILING ioctl
* we shouldn't advertise the tiled formats.
*/
if (screen->has_tiling_ioctl) {
m = 0;
*num = 2;
} else{
m = 1;
*num = 1;
}
return &all_modifiers[m];
}
static void
vc4_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
enum pipe_format format, int max,
......@@ -418,14 +442,12 @@ vc4_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
unsigned int *external_only,
int *count)
{
int m, i;
const uint64_t *available_modifiers;
int i;
bool tex_will_lower;
uint64_t available_modifiers[] = {
DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
DRM_FORMAT_MOD_LINEAR,
};
struct vc4_screen *screen = vc4_screen(pscreen);
int num_modifiers = screen->has_tiling_ioctl ? 2 : 1;
int num_modifiers;
available_modifiers = vc4_get_modifiers(pscreen, &num_modifiers);
if (!modifiers) {
*count = num_modifiers;
......@@ -433,19 +455,37 @@ vc4_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
}
*count = MIN2(max, num_modifiers);
m = screen->has_tiling_ioctl ? 0 : 1;
tex_will_lower = !vc4_tex_format_supported(format);
/* We support both modifiers (tiled and linear) for all sampler
* formats, but if we don't have the DRM_VC4_GET_TILING ioctl
* we shouldn't advertise the tiled formats.
*/
for (i = 0; i < *count; i++) {
modifiers[i] = available_modifiers[m++];
modifiers[i] = available_modifiers[i];
if (external_only)
external_only[i] = tex_will_lower;
}
}
static bool
vc4_screen_is_dmabuf_modifier_supported(struct pipe_screen *pscreen,
uint64_t modifier,
enum pipe_format format,
bool *external_only)
{
const uint64_t *available_modifiers;
int i, num_modifiers;
available_modifiers = vc4_get_modifiers(pscreen, &num_modifiers);
for (i = 0; i < num_modifiers; i++) {
if (modifier == available_modifiers[i]) {
if (external_only)
*external_only = !vc4_tex_format_supported(format);
return true;
}
}
return false;
}
static bool
vc4_get_chip_info(struct vc4_screen *screen)
{
......@@ -563,6 +603,7 @@ vc4_screen_create(int fd, struct renderonly *ro)
pscreen->get_device_vendor = vc4_screen_get_vendor;