diff mbox

[1/5] drm/i915: Fix sprite destination colorkeying on SKL+

Message ID 20180529182804.8571-1-ville.syrjala@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ville Syrjälä May 29, 2018, 6:28 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

On SKL+ the dst colorkey must be configured on the lower
plane that contains the colorkey. This is in contrast to
most earlier platforms where the dst colorkey is configured
on the plane above.

The hardware will peform dst keying only between two immediately
adjacent (in zorder) planes. Plane 1 will be keyed against plane 0,
plane 2 againts plane 1, and so on. There is no way to key arbitrary
planes against plane 0. Thus offering dst color keying on plane 2+
is pointless. In fact it can be harmful since enabling dst keying on
more than one plane on the same pipe leads to only the top-most of
the planes performing the keying. For any plane lower in zorder the
dst key enable is simply ignored.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_sprite.c | 63 +++++++++++++++++++++++++++++++++++--
 1 file changed, 60 insertions(+), 3 deletions(-)

Comments

Stanislav Lisovskiy June 5, 2018, 8:10 a.m. UTC | #1
On Tue, 2018-05-29 at 21:28 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>

> 

> On SKL+ the dst colorkey must be configured on the lower

> plane that contains the colorkey. This is in contrast to

> most earlier platforms where the dst colorkey is configured

> on the plane above.

> 

> The hardware will peform dst keying only between two immediately

> adjacent (in zorder) planes. Plane 1 will be keyed against plane 0,

> plane 2 againts plane 1, and so on. There is no way to key arbitrary

> planes against plane 0. Thus offering dst color keying on plane 2+

> is pointless. In fact it can be harmful since enabling dst keying on

> more than one plane on the same pipe leads to only the top-most of

> the planes performing the keying. For any plane lower in zorder the

> dst key enable is simply ignored.

> 

> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>


Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>


> ---

>  drivers/gpu/drm/i915/intel_sprite.c | 63

> +++++++++++++++++++++++++++++++++++--

>  1 file changed, 60 insertions(+), 3 deletions(-)

> 

> diff --git a/drivers/gpu/drm/i915/intel_sprite.c

> b/drivers/gpu/drm/i915/intel_sprite.c

> index ee23613f9fd4..6164c2ca20c3 100644

> --- a/drivers/gpu/drm/i915/intel_sprite.c

> +++ b/drivers/gpu/drm/i915/intel_sprite.c

> @@ -1071,6 +1071,36 @@ intel_check_sprite_plane(struct intel_plane

> *plane,

>  	return 0;

>  }

>  

> +static bool has_dst_key_in_primary_plane(struct drm_i915_private

> *dev_priv)

> +{

> +	return INTEL_GEN(dev_priv) >= 9;

> +}

> +

> +static void intel_plane_set_ckey(struct intel_plane_state

> *plane_state,

> +				 const struct

> drm_intel_sprite_colorkey *set)

> +{

> +	struct intel_plane *plane = to_intel_plane(plane_state-

> >base.plane);

> +	struct drm_intel_sprite_colorkey *key = &plane_state->ckey;

> +

> +	*key = *set;

> +

> +	/*

> +	 * We want src key enabled on the

> +	 * sprite and not on the primary.

> +	 */

> +	if (plane->id == PLANE_PRIMARY &&

> +	    set->flags & I915_SET_COLORKEY_SOURCE)

> +		key->flags = 0;

> +

> +	/*

> +	 * On SKL+ we want dst key enabled on

> +	 * the primary and not on the sprite.

> +	 */

> +	if (plane->id != PLANE_PRIMARY &&

> +	    set->flags & I915_SET_COLORKEY_DESTINATION)

> +		key->flags = 0;

> +}

> +

>  int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void

> *data,

>  				    struct drm_file *file_priv)

>  {

> @@ -1100,6 +1130,16 @@ int intel_sprite_set_colorkey_ioctl(struct

> drm_device *dev, void *data,

>  	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)

>  		return -ENOENT;

>  

> +	/*

> +	 * SKL+ only plane 1 can do destination keying against plane

> 0.

> +	 * Also multiple planes can't do destination keying on the

> same

> +	 * pipe simultaneously.

> +	 */

> +	if (INTEL_GEN(dev_priv) >= 9 &&

> +	    to_intel_plane(plane)->id >= PLANE_SPRITE1 &&

> +	    set->flags & I915_SET_COLORKEY_DESTINATION)

> +		return -EINVAL;

> +

>  	drm_modeset_acquire_init(&ctx, 0);

>  

>  	state = drm_atomic_state_alloc(plane->dev);

> @@ -1112,11 +1152,28 @@ int intel_sprite_set_colorkey_ioctl(struct

> drm_device *dev, void *data,

>  	while (1) {

>  		plane_state = drm_atomic_get_plane_state(state,

> plane);

>  		ret = PTR_ERR_OR_ZERO(plane_state);

> -		if (!ret) {

> -			to_intel_plane_state(plane_state)->ckey =

> *set;

> -			ret = drm_atomic_commit(state);

> +		if (!ret)

> +			intel_plane_set_ckey(to_intel_plane_state(pl

> ane_state), set);

> +

> +		/*

> +		 * On some platforms we have to configure

> +		 * the dst colorkey on the primary plane.

> +		 */

> +		if (!ret && has_dst_key_in_primary_plane(dev_priv))

> {

> +			struct intel_crtc *crtc =

> +				intel_get_crtc_for_pipe(dev_priv,

> +							to_intel_pla

> ne(plane)->pipe);

> +

> +			plane_state =

> drm_atomic_get_plane_state(state,

> +								 crt

> c->base.primary);

> +			ret = PTR_ERR_OR_ZERO(plane_state);

> +			if (!ret)

> +				intel_plane_set_ckey(to_intel_plane_

> state(plane_state), set);

>  		}

>  

> +		if (!ret)

> +			ret = drm_atomic_commit(state);

> +

>  		if (ret != -EDEADLK)

>  			break;

>  

-- 
Best Regards,

Lisovskiy Stanislav
Ville Syrjälä June 8, 2018, 6:29 p.m. UTC | #2
On Tue, Jun 05, 2018 at 08:10:36AM +0000, Lisovskiy, Stanislav wrote:
> On Tue, 2018-05-29 at 21:28 +0300, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > On SKL+ the dst colorkey must be configured on the lower
> > plane that contains the colorkey. This is in contrast to
> > most earlier platforms where the dst colorkey is configured
> > on the plane above.
> > 
> > The hardware will peform dst keying only between two immediately
> > adjacent (in zorder) planes. Plane 1 will be keyed against plane 0,
> > plane 2 againts plane 1, and so on. There is no way to key arbitrary
> > planes against plane 0. Thus offering dst color keying on plane 2+
> > is pointless. In fact it can be harmful since enabling dst keying on
> > more than one plane on the same pipe leads to only the top-most of
> > the planes performing the keying. For any plane lower in zorder the
> > dst key enable is simply ignored.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
> 
> > ---
> >  drivers/gpu/drm/i915/intel_sprite.c | 63
> > +++++++++++++++++++++++++++++++++++--
> >  1 file changed, 60 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_sprite.c
> > b/drivers/gpu/drm/i915/intel_sprite.c
> > index ee23613f9fd4..6164c2ca20c3 100644
> > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > @@ -1071,6 +1071,36 @@ intel_check_sprite_plane(struct intel_plane
> > *plane,
> >  	return 0;
> >  }
> >  
> > +static bool has_dst_key_in_primary_plane(struct drm_i915_private
> > *dev_priv)
> > +{
> > +	return INTEL_GEN(dev_priv) >= 9;
> > +}
> > +
> > +static void intel_plane_set_ckey(struct intel_plane_state
> > *plane_state,
> > +				 const struct
> > drm_intel_sprite_colorkey *set)
> > +{
> > +	struct intel_plane *plane = to_intel_plane(plane_state-
> > >base.plane);
> > +	struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> > +
> > +	*key = *set;
> > +
> > +	/*
> > +	 * We want src key enabled on the
> > +	 * sprite and not on the primary.
> > +	 */
> > +	if (plane->id == PLANE_PRIMARY &&
> > +	    set->flags & I915_SET_COLORKEY_SOURCE)
> > +		key->flags = 0;
> > +
> > +	/*
> > +	 * On SKL+ we want dst key enabled on
> > +	 * the primary and not on the sprite.
> > +	 */
> > +	if (plane->id != PLANE_PRIMARY &&

The 'INTEL_GEN(dev_priv) >= 9' check that was supposed to be here ended
up in the wrong patch. I moved it over while applying this to avoid
breaking the pre-SKL sprites. Only caught it when glancing at the
resulting code before pushing. Might be time to write some real
colorkeying igts...

Patch pushed to dinq. Thanks for the review.

> > +	    set->flags & I915_SET_COLORKEY_DESTINATION)
> > +		key->flags = 0;
> > +}
> > +
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index ee23613f9fd4..6164c2ca20c3 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1071,6 +1071,36 @@  intel_check_sprite_plane(struct intel_plane *plane,
 	return 0;
 }
 
+static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
+{
+	return INTEL_GEN(dev_priv) >= 9;
+}
+
+static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
+				 const struct drm_intel_sprite_colorkey *set)
+{
+	struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
+	struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
+
+	*key = *set;
+
+	/*
+	 * We want src key enabled on the
+	 * sprite and not on the primary.
+	 */
+	if (plane->id == PLANE_PRIMARY &&
+	    set->flags & I915_SET_COLORKEY_SOURCE)
+		key->flags = 0;
+
+	/*
+	 * On SKL+ we want dst key enabled on
+	 * the primary and not on the sprite.
+	 */
+	if (plane->id != PLANE_PRIMARY &&
+	    set->flags & I915_SET_COLORKEY_DESTINATION)
+		key->flags = 0;
+}
+
 int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
 				    struct drm_file *file_priv)
 {
@@ -1100,6 +1130,16 @@  int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
 	if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
 		return -ENOENT;
 
+	/*
+	 * SKL+ only plane 1 can do destination keying against plane 0.
+	 * Also multiple planes can't do destination keying on the same
+	 * pipe simultaneously.
+	 */
+	if (INTEL_GEN(dev_priv) >= 9 &&
+	    to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
+	    set->flags & I915_SET_COLORKEY_DESTINATION)
+		return -EINVAL;
+
 	drm_modeset_acquire_init(&ctx, 0);
 
 	state = drm_atomic_state_alloc(plane->dev);
@@ -1112,11 +1152,28 @@  int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
 	while (1) {
 		plane_state = drm_atomic_get_plane_state(state, plane);
 		ret = PTR_ERR_OR_ZERO(plane_state);
-		if (!ret) {
-			to_intel_plane_state(plane_state)->ckey = *set;
-			ret = drm_atomic_commit(state);
+		if (!ret)
+			intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
+
+		/*
+		 * On some platforms we have to configure
+		 * the dst colorkey on the primary plane.
+		 */
+		if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
+			struct intel_crtc *crtc =
+				intel_get_crtc_for_pipe(dev_priv,
+							to_intel_plane(plane)->pipe);
+
+			plane_state = drm_atomic_get_plane_state(state,
+								 crtc->base.primary);
+			ret = PTR_ERR_OR_ZERO(plane_state);
+			if (!ret)
+				intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
 		}
 
+		if (!ret)
+			ret = drm_atomic_commit(state);
+
 		if (ret != -EDEADLK)
 			break;