[PATCH 02/14] drm: add helper iterator functions for plane fb_damage_clips blob

Daniel Vetter daniel at ffwll.ch
Thu Sep 6 07:51:07 UTC 2018


On Wed, Sep 05, 2018 at 04:38:49PM -0700, Deepak Rawat wrote:
> With fb_damage_clips blob property in drm_plane_state, this patch adds
> helper iterator to traverse the damage clips that lie inside plane src.
> Iterator will return full plane src as damage in case need full plane
> update or damage is not specified.
> 
> Signed-off-by: Deepak Rawat <drawat at vmware.com>
> ---
>  drivers/gpu/drm/drm_damage_helper.c | 93 +++++++++++++++++++++++++++++
>  include/drm/drm_damage_helper.h     | 20 +++++++
>  2 files changed, 113 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c
> index 3e7de5afe7f6..7d70f6001889 100644
> --- a/drivers/gpu/drm/drm_damage_helper.c
> +++ b/drivers/gpu/drm/drm_damage_helper.c
> @@ -30,6 +30,7 @@
>   **************************************************************************/
>  
>  #include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
>  #include <drm/drm_damage_helper.h>
>  
>  /**
> @@ -75,6 +76,11 @@
>   * While kernel does not error for overlapped damage clips, it is discouraged.
>   */
>  
> +static int convert_fixed_to_32(int fixed)
> +{
> +	return ((fixed >> 15) & 1) + (fixed >> 16);
> +}
> +
>  /**
>   * drm_plane_enable_fb_damage_clips - enables plane fb damage clips property
>   * @plane: plane on which to enable damage clips property
> @@ -90,3 +96,90 @@ void drm_plane_enable_fb_damage_clips(struct drm_plane *plane)
>  				   0);
>  }
>  EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips);
> +
> +/**
> + * drm_atomic_helper_damage_iter_init - initialize the damage iterator
> + * @iter: The iterator to initialize.
> + * @old_state: old plane state for validation.
> + * @new_state: plane state from which to iterate the damage clips.
> + *
> + * Initialize an iterator that clip framebuffer damage in plane fb_damage_clips
> + * blob to plane src clip. The iterator returns full plane src in case needing
> + * full update e.g. during full modeset.
> + *
> + * With this helper iterator, drivers which enabled fb_damage_clips property can
> + * iterate over the damage clips that falls inside plane src during plane
> + * update.
> + *
> + * Returns: 0 on success and negative error code on error. If an error code is
> + * returned then it means the plane state shouldn't update with attached fb.
> + */
> +int
> +drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
> +				   const struct drm_plane_state *old_state,
> +				   const struct drm_plane_state *new_state)
> +{
> +	if (!new_state || !new_state->crtc || !new_state->fb)
> +		return -EINVAL;
> +
> +	if (!new_state->visible)
> +		return -EINVAL;

Can't we handle this by iterating 0 damage rects instead? Would make the
code a bit cleaner I think.

> +
> +	memset(iter, 0, sizeof(*iter));
> +	iter->clips = drm_plane_get_damage_clips(new_state);
> +	iter->num_clips = drm_plane_get_damage_clips_count(new_state);
> +
> +	if (!iter->clips)
> +		iter->full_update = true;
> +
> +	if (!drm_rect_equals(&new_state->src, &old_state->src))
> +		iter->full_update = true;
> +
> +	iter->plane_src.x1 = convert_fixed_to_32(new_state->src.x1);
> +	iter->plane_src.y1 = convert_fixed_to_32(new_state->src.y1);
> +	iter->plane_src.x2 = convert_fixed_to_32(new_state->src.x2);
> +	iter->plane_src.y2 = convert_fixed_to_32(new_state->src.y2);

I think you want to clip with the clipped rectangles here, not with the
ones userspace provides.

Also I think you're rounding is wrong here - I think you need to round
down for x/y1, and round up for x/y2 to make sure you catch all the
pixels?

Unit tests for this, in the form of a drm selftest (like we have for
drm_mm.c already, but for kms helpers) would be perfect. Much easier to
review a testcase than do bitmath in my head :-)

> +
> +	if (iter->full_update) {
> +		iter->clips = 0;
> +		iter->curr_clip = 0;
> +		iter->num_clips = 0;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_atomic_helper_damage_iter_init);
> +
> +/**
> + * drm_atomic_helper_damage_iter_next - advance the damage iterator
> + * @iter: The iterator to advance.
> + * @rect: Return a rectangle in fb coordinate clipped to plane src.
> + *
> + * Returns:  true if the output is valid, false if we've reached the end of the
> + * rectangle list.
> + */
> +bool
> +drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter,
> +				   struct drm_rect *rect)
> +{
> +	bool ret = false;
> +
> +	if (iter->full_update) {
> +		*rect = iter->plane_src;
> +		iter->full_update = false;
> +		return true;
> +	}
> +
> +	while (iter->curr_clip < iter->num_clips) {
> +		*rect = iter->clips[iter->curr_clip];
> +		iter->curr_clip++;
> +
> +		if (drm_rect_intersect(rect, &iter->plane_src)) {
> +			ret = true;
> +			break;
> +		}
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(drm_atomic_helper_damage_iter_next);
> diff --git a/include/drm/drm_damage_helper.h b/include/drm/drm_damage_helper.h
> index 217694e9168c..f1282b459a4f 100644
> --- a/include/drm/drm_damage_helper.h
> +++ b/include/drm/drm_damage_helper.h
> @@ -32,6 +32,19 @@
>  #ifndef DRM_DAMAGE_HELPER_H_
>  #define DRM_DAMAGE_HELPER_H_
>  
> +/**
> + * struct drm_atomic_helper_damage_iter - damage clip iterator
> + *
> + * This iterator tracks state needed to walk the list of damage clips.
> + */
> +struct drm_atomic_helper_damage_iter {
> +	const struct drm_rect *clips;
> +	struct drm_rect plane_src;
> +	uint32_t num_clips;
> +	uint32_t curr_clip;
> +	bool full_update;
> +};
> +
>  /**
>   * drm_plane_get_damage_clips_count - returns damage clips count
>   * @state: Plane state
> @@ -59,5 +72,12 @@ drm_plane_get_damage_clips(const struct drm_plane_state *state)
>  }
>  
>  void drm_plane_enable_fb_damage_clips(struct drm_plane *plane);
> +int
> +drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
> +				   const struct drm_plane_state *old_state,
> +				   const struct drm_plane_state *new_state);

I think a for_each_damage macro would be sweet on top of these here. But
easy to add later on.
-Daniel

> +bool
> +drm_atomic_helper_damage_iter_next(struct drm_atomic_helper_damage_iter *iter,
> +				   struct drm_rect *rect);
>  
>  #endif
> -- 
> 2.17.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the dri-devel mailing list