[PATCH 2/3] drm/i915: Add format modifiers for Intel

Ben Widawsky ben at bwidawsk.net
Thu Jan 12 18:56:17 UTC 2017


On 17-01-12 20:32:07, Ville Syrjälä wrote:
>On Thu, Jan 12, 2017 at 10:00:55AM -0800, Ben Widawsky wrote:
>> On 17-01-12 12:51:20, Ville Syrjälä wrote:
>> >On Wed, Jan 11, 2017 at 04:51:17PM -0800, Ben Widawsky wrote:
>> >> This was based on a patch originally by Kristian. It has been modified
>> >> pretty heavily to use the new callbacks from the previous patch.
>> >>
>> >> Cc: Kristian H. Kristensen <hoegsberg at gmail.com>
>> >> Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
>> >> ---
>> >>  drivers/gpu/drm/i915/intel_display.c | 109 ++++++++++++++++++++++++++++++++++-
>> >>  drivers/gpu/drm/i915/intel_sprite.c  |  33 ++++++++++-
>> >>  2 files changed, 137 insertions(+), 5 deletions(-)
>> >>
>> >> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> >> index 8715b1083d1d..26f3a911b999 100644
>> >> --- a/drivers/gpu/drm/i915/intel_display.c
>> >> +++ b/drivers/gpu/drm/i915/intel_display.c
>> >> @@ -61,6 +61,11 @@ static const uint32_t i8xx_primary_formats[] = {
>> >>  	DRM_FORMAT_XRGB8888,
>> >>  };
>> >>
>> >> +static const uint64_t i8xx_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >
>> >Did we want to list the linear modifier in these as well?
>> >
>>
>> Yeah. My initial response was no, but yes. We should. I was using
>> DRM_FORMAT_MOD_NONE in its place, it should be linear, and it should be defined
>> in the array.
>>
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  /* Primary plane formats for gen >= 4 */
>> >>  static const uint32_t i965_primary_formats[] = {
>> >>  	DRM_FORMAT_C8,
>> >> @@ -71,6 +76,11 @@ static const uint32_t i965_primary_formats[] = {
>> >>  	DRM_FORMAT_XBGR2101010,
>> >>  };
>> >>
>> >> +static const uint64_t i965_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >
>> >We could just share the i8xx array. The name of the array should perhaps
>> >be i9xx_format_modifiers[] in that case. That's sort of the naming
>> >convention we've been left with for things that apply to more or less
>> >all the platforms.
>> >
>>
>> Got it thanks. This is a relic from Kristian's original patch which tied the
>> modifiers to the formats in place. It made more sense there to have a separate
>> i8xx
>>
>> >> +
>> >>  static const uint32_t skl_primary_formats[] = {
>> >>  	DRM_FORMAT_C8,
>> >>  	DRM_FORMAT_RGB565,
>> >> @@ -86,6 +96,12 @@ static const uint32_t skl_primary_formats[] = {
>> >>  	DRM_FORMAT_VYUY,
>> >>  };
>> >>
>> >> +static const uint64_t skl_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_Y_TILED,
>> >
>> >Yf missing? and linear
>> >
>>
>> Yes, thanks. I'm kind of scared to add Yf to be honest :P
>>
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  /* Cursor formats */
>> >>  static const uint32_t intel_cursor_formats[] = {
>> >>  	DRM_FORMAT_ARGB8888,
>> >> @@ -15173,6 +15189,87 @@ void intel_plane_destroy(struct drm_plane *plane)
>> >>  	kfree(to_intel_plane(plane));
>> >>  }
>> >>
>> >> +static bool i8xx_mod_supported(uint32_t format, uint64_t modifier)
>> >> +{
>> >> +	if (modifier == DRM_FORMAT_MOD_NONE)
>> >> +		return true;
>> >> +
>> >> +	switch (format) {
>> >> +	case DRM_FORMAT_C8:
>> >> +	case DRM_FORMAT_RGB565:
>> >> +	case DRM_FORMAT_XRGB1555:
>> >> +	case DRM_FORMAT_XRGB8888:
>> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
>> >> +	default:
>> >> +		return false;
>> >> +	}
>> >> +}
>> >> +
>> >> +static bool i965_mod_supported(uint32_t format, uint64_t modifier)
>> >> +{
>> >> +	switch (format) {
>> >> +	case DRM_FORMAT_C8:
>> >> +	case DRM_FORMAT_RGB565:
>> >> +	case DRM_FORMAT_XRGB8888:
>> >> +	case DRM_FORMAT_XBGR8888:
>> >> +	case DRM_FORMAT_XRGB2101010:
>> >> +	case DRM_FORMAT_XBGR2101010:
>> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
>> >> +	default:
>> >> +		return false;
>> >> +	}
>> >> +}
>> >
>> >Hmm. There should be no format vs. tiling restrictions on these
>> >platforms, so presumably a simple "return true" should cover it all.
>> >That does perhaps remove the usefulness of these functions for
>> >verifying that the format or modifier is supported at all
>>
>> One of the reasons for changing to this current format-modifier lookup at all
>> was Kristian's approach was considered fragile. If for whatever reason formats
>> are added, or removed, we'll catch it here. Also, it maybe let's us do something
>> on cursor plane at some point (I don't actually know). So yeah, we can return
>> true, but I like that it's spelled out explicitly. Makes it easy to compare it
>> to the docs as well to make sure our code is correct.
>>
>> The benefit is of course I can combine i965_mod_supported() with
>> i8xx_mod_supported()
>>
>> I'm honestly fine with changing it as well, I just don't see a huge reason to
>> change it since I've already typed it up. I'll leave it to you.
>
>Feel free to keep it. We can always change it later if it becomes too much
>work to maintain the duplicated format lists (the function and the array).
>Not that I really expect these lists to be all that volatile.
>
>>
>> [ ] Yes, change it.
>> [ ] No, leave it.
>>
>> >but I've been thinking that addfb should perhaps just iterate through the
>> >format and modifier lists for every plane. Would avoid having to effectively
>> >maintain the same lists in multiple places.
>> >
>>
>> I don't quite follow this. Can you elaborate?
>
>I was just thinking that instead of addfb passing in an unverified format
>to the driver's .fb_create() hook, it could first go through the format
>lists of each plane, and make sure at least one of them supports the
>requested format. That way we could eliminate that fragile pixel_format
>switch statement from intel_framebuffer_init().
>
>But if you plan on making the .format_mod_supported() hooks 100%
>strict, then we could use that instead. Would avoid having to walk
>the format lists of every plane at least.
>

Let's keep it the way things are for now, mostly because I'm lazy and this
works.

>>
>> >> +
>> >> +static bool skl_mod_supported(uint32_t format, uint64_t modifier)
>> >> +{
>> >> +	switch (format) {
>> >> +	case DRM_FORMAT_C8:
>> >> +	case DRM_FORMAT_RGB565:
>> >> +	case DRM_FORMAT_XRGB8888:
>> >> +	case DRM_FORMAT_XBGR8888:
>> >> +	case DRM_FORMAT_ARGB8888:
>> >> +	case DRM_FORMAT_ABGR8888:
>> >> +		return modifier == I915_FORMAT_MOD_Y_TILED ||
>> >> +			modifier == I915_FORMAT_MOD_X_TILED;
>> >> +	case DRM_FORMAT_XRGB2101010:
>> >> +	case DRM_FORMAT_XBGR2101010:
>> >> +		return modifier == I915_FORMAT_MOD_X_TILED;
>> >> +	case DRM_FORMAT_YUYV:
>> >> +	case DRM_FORMAT_YVYU:
>> >> +	case DRM_FORMAT_UYVY:
>> >> +	case DRM_FORMAT_VYUY:
>> >
>> >IIRC on SKL the only restrictions should be that CCS modifiers are
>> >limited to 8:8:8:8 formats only. Other modifiers should work
>> >with any format.
>> >
>>
>> This restriction was copied from Kristian's patch. I just checked the docs and
>> you are correct. So this needs Yf modifier too. (Aside from CCS, rotation is the
>> one case: x-tiled 1010102 isn't supported).
>
>I can't see any extra restrictions for 10bpc formats.
>
>The only exception I see for 0/180 degree rotation is FP16 not being
>supported with Yf. And since we don't actually expose FP16 we don't have
>to worry about it. So apart from the CCS+8:8:8:8 cases all other
>format+modifier combos should be perfectly fine AFAICS.
>
>My information was gleaned from the "plane capability" table in the
>spec, but I wasn't able to immediately spot any additional restriction
>in the PLANE_CTL register description either.
>

Sorry for making you verify that, I think you are correct and I'm misreading the
table. I was just looking at the specific columns: Linear and X-tiled 90/270
rotation aren't supported with 1010102, but they aren't supported with any other
surface format either.

However, looking again now, it looks like DRM_FORMAT_C8 doesn't support Yf.

>>
>> >> +	default:
>> >> +		return false;
>> >> +	}
>> >> +
>> >> +}
>> >> +
>> >> +static bool intel_plane_format_mod_supported(struct drm_plane *plane,
>> >> +					     uint32_t format,
>> >> +					     uint64_t modifier)
>> >> +{
>> >> +	struct drm_i915_private *dev_priv = to_i915(plane->dev);
>> >> +
>> >> +	if (modifier == DRM_FORMAT_MOD_NONE)
>> >> +		return true;
>> >> +
>> >> +	if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
>> >> +		return false;
>> >> +
>> >> +	if (WARN_ON(plane->type != DRM_PLANE_TYPE_PRIMARY &&
>> >> +		    plane->type != DRM_PLANE_TYPE_OVERLAY))
>> >> +	    return false;
>> >> +
>> >> +	if (INTEL_GEN(dev_priv) >= 9)
>> >> +		return skl_mod_supported(format, modifier);
>> >> +	else if (INTEL_GEN(dev_priv) >= 4)
>> >> +		return i965_mod_supported(format, modifier);
>> >> +	else
>> >> +		return i8xx_mod_supported(format, modifier);
>> >> +
>> >> +	return false;
>> >> +}
>> >> +
>> >>  const struct drm_plane_funcs intel_plane_funcs = {
>> >>  	.update_plane = drm_atomic_helper_update_plane,
>> >>  	.disable_plane = drm_atomic_helper_disable_plane,
>> >> @@ -15182,6 +15279,7 @@ const struct drm_plane_funcs intel_plane_funcs = {
>> >>  	.atomic_set_property = intel_plane_atomic_set_property,
>> >>  	.atomic_duplicate_state = intel_plane_duplicate_state,
>> >>  	.atomic_destroy_state = intel_plane_destroy_state,
>> >> +	.format_mod_supported = intel_plane_format_mod_supported,
>> >>  };
>> >>
>> >>  static int
>> >> @@ -15324,6 +15422,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>> >>  	const uint32_t *intel_primary_formats;
>> >>  	unsigned int supported_rotations;
>> >>  	unsigned int num_formats;
>> >> +	const uint64_t *intel_format_modifiers;
>> >>  	int ret;
>> >>
>> >>  	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
>> >> @@ -15362,24 +15461,28 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>> >>  	if (INTEL_GEN(dev_priv) >= 9) {
>> >>  		intel_primary_formats = skl_primary_formats;
>> >>  		num_formats = ARRAY_SIZE(skl_primary_formats);
>> >> +		intel_format_modifiers = skl_format_modifiers;
>> >>
>> >>  		primary->update_plane = skylake_update_primary_plane;
>> >>  		primary->disable_plane = skylake_disable_primary_plane;
>> >>  	} else if (HAS_PCH_SPLIT(dev_priv)) {
>> >>  		intel_primary_formats = i965_primary_formats;
>> >>  		num_formats = ARRAY_SIZE(i965_primary_formats);
>> >> +		intel_format_modifiers = i965_format_modifiers;
>> >>
>> >>  		primary->update_plane = ironlake_update_primary_plane;
>> >>  		primary->disable_plane = i9xx_disable_primary_plane;
>> >>  	} else if (INTEL_GEN(dev_priv) >= 4) {
>> >>  		intel_primary_formats = i965_primary_formats;
>> >>  		num_formats = ARRAY_SIZE(i965_primary_formats);
>> >> +		intel_format_modifiers = i965_format_modifiers;
>> >>
>> >>  		primary->update_plane = i9xx_update_primary_plane;
>> >>  		primary->disable_plane = i9xx_disable_primary_plane;
>> >>  	} else {
>> >>  		intel_primary_formats = i8xx_primary_formats;
>> >>  		num_formats = ARRAY_SIZE(i8xx_primary_formats);
>> >> +		intel_format_modifiers = i8xx_format_modifiers;
>> >>
>> >>  		primary->update_plane = i9xx_update_primary_plane;
>> >>  		primary->disable_plane = i9xx_disable_primary_plane;
>> >> @@ -15389,21 +15492,21 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
>> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>> >>  					       0, &intel_plane_funcs,
>> >>  					       intel_primary_formats, num_formats,
>> >> -					       NULL,
>> >> +					       intel_format_modifiers,
>> >>  					       DRM_PLANE_TYPE_PRIMARY,
>> >>  					       "plane 1%c", pipe_name(pipe));
>> >>  	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
>> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>> >>  					       0, &intel_plane_funcs,
>> >>  					       intel_primary_formats, num_formats,
>> >> -					       NULL,
>> >> +					       intel_format_modifiers,
>> >>  					       DRM_PLANE_TYPE_PRIMARY,
>> >>  					       "primary %c", pipe_name(pipe));
>> >>  	else
>> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
>> >>  					       0, &intel_plane_funcs,
>> >>  					       intel_primary_formats, num_formats,
>> >> -					       NULL,
>> >> +					       intel_format_modifiers,
>> >>  					       DRM_PLANE_TYPE_PRIMARY,
>> >>  					       "plane %c", plane_name(primary->plane));
>> >>  	if (ret)
>> >> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
>> >> index 1c2f26d86f76..152ec8196d41 100644
>> >> --- a/drivers/gpu/drm/i915/intel_sprite.c
>> >> +++ b/drivers/gpu/drm/i915/intel_sprite.c
>> >> @@ -994,6 +994,11 @@ static const uint32_t ilk_plane_formats[] = {
>> >>  	DRM_FORMAT_VYUY,
>> >>  };
>> >>
>> >> +static const uint64_t ilk_plane_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  static const uint32_t snb_plane_formats[] = {
>> >>  	DRM_FORMAT_XBGR8888,
>> >>  	DRM_FORMAT_XRGB8888,
>> >> @@ -1003,6 +1008,11 @@ static const uint32_t snb_plane_formats[] = {
>> >>  	DRM_FORMAT_VYUY,
>> >>  };
>> >>
>> >> +static const uint64_t snb_plane_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  static const uint32_t vlv_plane_formats[] = {
>> >>  	DRM_FORMAT_RGB565,
>> >>  	DRM_FORMAT_ABGR8888,
>> >> @@ -1017,6 +1027,11 @@ static const uint32_t vlv_plane_formats[] = {
>> >>  	DRM_FORMAT_VYUY,
>> >>  };
>> >>
>> >> +static const uint64_t vlv_plane_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  static uint32_t skl_plane_formats[] = {
>> >>  	DRM_FORMAT_RGB565,
>> >>  	DRM_FORMAT_ABGR8888,
>> >> @@ -1029,6 +1044,12 @@ static uint32_t skl_plane_formats[] = {
>> >>  	DRM_FORMAT_VYUY,
>> >>  };
>> >>
>> >> +static const uint64_t skl_plane_format_modifiers[] = {
>> >> +	I915_FORMAT_MOD_Y_TILED,
>> >> +	I915_FORMAT_MOD_X_TILED,
>> >> +	DRM_FORMAT_MOD_INVALID
>> >> +};
>> >> +
>> >>  struct intel_plane *
>> >>  intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>  			  enum pipe pipe, int plane)
>> >> @@ -1037,6 +1058,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>  	struct intel_plane_state *state = NULL;
>> >>  	unsigned long possible_crtcs;
>> >>  	const uint32_t *plane_formats;
>> >> +	const uint64_t *modifiers;
>> >>  	unsigned int supported_rotations;
>> >>  	int num_plane_formats;
>> >>  	int ret;
>> >> @@ -1063,6 +1085,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>
>> >>  		plane_formats = skl_plane_formats;
>> >>  		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
>> >> +		modifiers = skl_plane_format_modifiers;
>> >>  	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
>> >>  		intel_plane->can_scale = false;
>> >>  		intel_plane->max_downscale = 1;
>> >> @@ -1072,6 +1095,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>
>> >>  		plane_formats = vlv_plane_formats;
>> >>  		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
>> >> +		modifiers = vlv_plane_format_modifiers;
>> >>  	} else if (INTEL_GEN(dev_priv) >= 7) {
>> >>  		if (IS_IVYBRIDGE(dev_priv)) {
>> >>  			intel_plane->can_scale = true;
>> >> @@ -1086,6 +1110,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>
>> >>  		plane_formats = snb_plane_formats;
>> >>  		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
>> >> +		modifiers = snb_plane_format_modifiers;
>> >>  	} else {
>> >>  		intel_plane->can_scale = true;
>> >>  		intel_plane->max_downscale = 16;
>> >> @@ -1096,9 +1121,11 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>  		if (IS_GEN6(dev_priv)) {
>> >>  			plane_formats = snb_plane_formats;
>> >>  			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
>> >> +			modifiers = snb_plane_format_modifiers;
>> >>  		} else {
>> >>  			plane_formats = ilk_plane_formats;
>> >>  			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
>> >> +			modifiers = ilk_plane_format_modifiers;
>> >>  		}
>> >>  	}
>> >>
>> >> @@ -1127,13 +1154,15 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
>> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>> >>  					       possible_crtcs, &intel_plane_funcs,
>> >>  					       plane_formats, num_plane_formats,
>> >> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
>> >> +					       modifiers,
>> >> +					       DRM_PLANE_TYPE_OVERLAY,
>> >>  					       "plane %d%c", plane + 2, pipe_name(pipe));
>> >>  	else
>> >>  		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
>> >>  					       possible_crtcs, &intel_plane_funcs,
>> >>  					       plane_formats, num_plane_formats,
>> >> -					       NULL, DRM_PLANE_TYPE_OVERLAY,
>> >> +					       modifiers,
>> >> +					       DRM_PLANE_TYPE_OVERLAY,
>> >>  					       "sprite %c", sprite_name(pipe, plane));
>> >>  	if (ret)
>> >>  		goto fail;
>> >> --
>> >> 2.11.0
>> >>
>> >> _______________________________________________
>> >> dri-devel mailing list
>> >> dri-devel at lists.freedesktop.org
>> >> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>> >
>> >--
>> >Ville Syrjälä
>> >Intel OTC
>
>-- 
>Ville Syrjälä
>Intel OTC


More information about the dri-devel mailing list