mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	drm/plane-helper: Add drm_plane_helper_check_state()
Add a version of drm_plane_helper_check_update() which takes a plane state instead of having the caller pass in everything. And to reduce code duplication, let's reimplement drm_plane_helper_check_update() in terms of the new function, by having a tempororary plane state on the stack. v2: Add a note that the functions modifies the state (Chris) v3: Fix drm_plane_helper_check_update() y coordinates (Daniel Kurtz) Cc: Daniel Kurtz <djkurtz@chromium.org> Cc: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Sean Paul <seanpaul@chromium.org> (v2) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Sean Paul <seanpaul@chromium.org> Link: http://patchwork.freedesktop.org/patch/msgid/1470642910-14073-1-git-send-email-ville.syrjala@linux.intel.com
This commit is contained in:
		
							parent
							
								
									d7da824d9e
								
							
						
					
					
						commit
						df86af9133
					
				
					 2 changed files with 129 additions and 49 deletions
				
			
		| 
						 | 
				
			
			@ -107,6 +107,104 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
 | 
			
		|||
	return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * drm_plane_helper_check_state() - Check plane state for validity
 | 
			
		||||
 * @state: plane state to check
 | 
			
		||||
 * @clip: integer clipping coordinates
 | 
			
		||||
 * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
 | 
			
		||||
 * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
 | 
			
		||||
 * @can_position: is it legal to position the plane such that it
 | 
			
		||||
 *                doesn't cover the entire crtc?  This will generally
 | 
			
		||||
 *                only be false for primary planes.
 | 
			
		||||
 * @can_update_disabled: can the plane be updated while the crtc
 | 
			
		||||
 *                       is disabled?
 | 
			
		||||
 *
 | 
			
		||||
 * Checks that a desired plane update is valid, and updates various
 | 
			
		||||
 * bits of derived state (clipped coordinates etc.). Drivers that provide
 | 
			
		||||
 * their own plane handling rather than helper-provided implementations may
 | 
			
		||||
 * still wish to call this function to avoid duplication of error checking
 | 
			
		||||
 * code.
 | 
			
		||||
 *
 | 
			
		||||
 * RETURNS:
 | 
			
		||||
 * Zero if update appears valid, error code on failure
 | 
			
		||||
 */
 | 
			
		||||
int drm_plane_helper_check_state(struct drm_plane_state *state,
 | 
			
		||||
				 const struct drm_rect *clip,
 | 
			
		||||
				 int min_scale,
 | 
			
		||||
				 int max_scale,
 | 
			
		||||
				 bool can_position,
 | 
			
		||||
				 bool can_update_disabled)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_crtc *crtc = state->crtc;
 | 
			
		||||
	struct drm_framebuffer *fb = state->fb;
 | 
			
		||||
	struct drm_rect *src = &state->src;
 | 
			
		||||
	struct drm_rect *dst = &state->dst;
 | 
			
		||||
	unsigned int rotation = state->rotation;
 | 
			
		||||
	int hscale, vscale;
 | 
			
		||||
 | 
			
		||||
	src->x1 = state->src_x;
 | 
			
		||||
	src->y1 = state->src_y;
 | 
			
		||||
	src->x2 = state->src_x + state->src_w;
 | 
			
		||||
	src->y2 = state->src_y + state->src_h;
 | 
			
		||||
 | 
			
		||||
	dst->x1 = state->crtc_x;
 | 
			
		||||
	dst->y1 = state->crtc_y;
 | 
			
		||||
	dst->x2 = state->crtc_x + state->crtc_w;
 | 
			
		||||
	dst->y2 = state->crtc_y + state->crtc_h;
 | 
			
		||||
 | 
			
		||||
	if (!fb) {
 | 
			
		||||
		state->visible = false;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* crtc should only be NULL when disabling (i.e., !fb) */
 | 
			
		||||
	if (WARN_ON(!crtc)) {
 | 
			
		||||
		state->visible = false;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!crtc->enabled && !can_update_disabled) {
 | 
			
		||||
		DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
 | 
			
		||||
 | 
			
		||||
	/* Check scaling */
 | 
			
		||||
	hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
 | 
			
		||||
	vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
 | 
			
		||||
	if (hscale < 0 || vscale < 0) {
 | 
			
		||||
		DRM_DEBUG_KMS("Invalid scaling of plane\n");
 | 
			
		||||
		drm_rect_debug_print("src: ", &state->src, true);
 | 
			
		||||
		drm_rect_debug_print("dst: ", &state->dst, false);
 | 
			
		||||
		return -ERANGE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
 | 
			
		||||
 | 
			
		||||
	drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
 | 
			
		||||
 | 
			
		||||
	if (!state->visible)
 | 
			
		||||
		/*
 | 
			
		||||
		 * Plane isn't visible; some drivers can handle this
 | 
			
		||||
		 * so we just return success here.  Drivers that can't
 | 
			
		||||
		 * (including those that use the primary plane helper's
 | 
			
		||||
		 * update function) will return an error from their
 | 
			
		||||
		 * update_plane handler.
 | 
			
		||||
		 */
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!can_position && !drm_rect_equals(dst, clip)) {
 | 
			
		||||
		DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
 | 
			
		||||
		drm_rect_debug_print("dst: ", dst, false);
 | 
			
		||||
		drm_rect_debug_print("clip: ", clip, false);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(drm_plane_helper_check_state);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * drm_plane_helper_check_update() - Check plane update for validity
 | 
			
		||||
 * @plane: plane object to update
 | 
			
		||||
| 
						 | 
				
			
			@ -138,7 +236,7 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
 | 
			
		|||
				  struct drm_crtc *crtc,
 | 
			
		||||
				  struct drm_framebuffer *fb,
 | 
			
		||||
				  struct drm_rect *src,
 | 
			
		||||
				  struct drm_rect *dest,
 | 
			
		||||
				  struct drm_rect *dst,
 | 
			
		||||
				  const struct drm_rect *clip,
 | 
			
		||||
				  unsigned int rotation,
 | 
			
		||||
				  int min_scale,
 | 
			
		||||
| 
						 | 
				
			
			@ -147,56 +245,33 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
 | 
			
		|||
				  bool can_update_disabled,
 | 
			
		||||
				  bool *visible)
 | 
			
		||||
{
 | 
			
		||||
	int hscale, vscale;
 | 
			
		||||
	struct drm_plane_state state = {
 | 
			
		||||
		.plane = plane,
 | 
			
		||||
		.crtc = crtc,
 | 
			
		||||
		.fb = fb,
 | 
			
		||||
		.src_x = src->x1,
 | 
			
		||||
		.src_y = src->y1,
 | 
			
		||||
		.src_w = drm_rect_width(src),
 | 
			
		||||
		.src_h = drm_rect_height(src),
 | 
			
		||||
		.crtc_x = dst->x1,
 | 
			
		||||
		.crtc_y = dst->y1,
 | 
			
		||||
		.crtc_w = drm_rect_width(dst),
 | 
			
		||||
		.crtc_h = drm_rect_height(dst),
 | 
			
		||||
		.rotation = rotation,
 | 
			
		||||
		.visible = *visible,
 | 
			
		||||
	};
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (!fb) {
 | 
			
		||||
		*visible = false;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	ret = drm_plane_helper_check_state(&state, clip,
 | 
			
		||||
					   min_scale, max_scale,
 | 
			
		||||
					   can_position,
 | 
			
		||||
					   can_update_disabled);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	/* crtc should only be NULL when disabling (i.e., !fb) */
 | 
			
		||||
	if (WARN_ON(!crtc)) {
 | 
			
		||||
		*visible = false;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!crtc->enabled && !can_update_disabled) {
 | 
			
		||||
		DRM_DEBUG_KMS("Cannot update plane of a disabled CRTC.\n");
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
 | 
			
		||||
 | 
			
		||||
	/* Check scaling */
 | 
			
		||||
	hscale = drm_rect_calc_hscale(src, dest, min_scale, max_scale);
 | 
			
		||||
	vscale = drm_rect_calc_vscale(src, dest, min_scale, max_scale);
 | 
			
		||||
	if (hscale < 0 || vscale < 0) {
 | 
			
		||||
		DRM_DEBUG_KMS("Invalid scaling of plane\n");
 | 
			
		||||
		drm_rect_debug_print("src: ", src, true);
 | 
			
		||||
		drm_rect_debug_print("dst: ", dest, false);
 | 
			
		||||
		return -ERANGE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*visible = drm_rect_clip_scaled(src, dest, clip, hscale, vscale);
 | 
			
		||||
 | 
			
		||||
	drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation);
 | 
			
		||||
 | 
			
		||||
	if (!*visible)
 | 
			
		||||
		/*
 | 
			
		||||
		 * Plane isn't visible; some drivers can handle this
 | 
			
		||||
		 * so we just return success here.  Drivers that can't
 | 
			
		||||
		 * (including those that use the primary plane helper's
 | 
			
		||||
		 * update function) will return an error from their
 | 
			
		||||
		 * update_plane handler.
 | 
			
		||||
		 */
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (!can_position && !drm_rect_equals(dest, clip)) {
 | 
			
		||||
		DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
 | 
			
		||||
		drm_rect_debug_print("dst: ", dest, false);
 | 
			
		||||
		drm_rect_debug_print("clip: ", clip, false);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	*src = state.src;
 | 
			
		||||
	*dst = state.dst;
 | 
			
		||||
	*visible = state.visible;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,11 @@
 | 
			
		|||
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
 | 
			
		||||
		  const struct drm_crtc_funcs *funcs);
 | 
			
		||||
 | 
			
		||||
int drm_plane_helper_check_state(struct drm_plane_state *state,
 | 
			
		||||
				 const struct drm_rect *clip,
 | 
			
		||||
				 int min_scale, int max_scale,
 | 
			
		||||
				 bool can_position,
 | 
			
		||||
				 bool can_update_disabled);
 | 
			
		||||
int drm_plane_helper_check_update(struct drm_plane *plane,
 | 
			
		||||
				  struct drm_crtc *crtc,
 | 
			
		||||
				  struct drm_framebuffer *fb,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue