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;
 | 
						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
 | 
					 * drm_plane_helper_check_update() - Check plane update for validity
 | 
				
			||||||
 * @plane: plane object to update
 | 
					 * @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_crtc *crtc,
 | 
				
			||||||
				  struct drm_framebuffer *fb,
 | 
									  struct drm_framebuffer *fb,
 | 
				
			||||||
				  struct drm_rect *src,
 | 
									  struct drm_rect *src,
 | 
				
			||||||
				  struct drm_rect *dest,
 | 
									  struct drm_rect *dst,
 | 
				
			||||||
				  const struct drm_rect *clip,
 | 
									  const struct drm_rect *clip,
 | 
				
			||||||
				  unsigned int rotation,
 | 
									  unsigned int rotation,
 | 
				
			||||||
				  int min_scale,
 | 
									  int min_scale,
 | 
				
			||||||
| 
						 | 
					@ -147,56 +245,33 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
 | 
				
			||||||
				  bool can_update_disabled,
 | 
									  bool can_update_disabled,
 | 
				
			||||||
				  bool *visible)
 | 
									  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) {
 | 
						ret = drm_plane_helper_check_state(&state, clip,
 | 
				
			||||||
		*visible = false;
 | 
										   min_scale, max_scale,
 | 
				
			||||||
		return 0;
 | 
										   can_position,
 | 
				
			||||||
	}
 | 
										   can_update_disabled);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* crtc should only be NULL when disabling (i.e., !fb) */
 | 
						*src = state.src;
 | 
				
			||||||
	if (WARN_ON(!crtc)) {
 | 
						*dst = state.dst;
 | 
				
			||||||
		*visible = false;
 | 
						*visible = state.visible;
 | 
				
			||||||
		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;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,6 +40,11 @@
 | 
				
			||||||
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
 | 
					int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
 | 
				
			||||||
		  const struct drm_crtc_funcs *funcs);
 | 
							  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,
 | 
					int drm_plane_helper_check_update(struct drm_plane *plane,
 | 
				
			||||||
				  struct drm_crtc *crtc,
 | 
									  struct drm_crtc *crtc,
 | 
				
			||||||
				  struct drm_framebuffer *fb,
 | 
									  struct drm_framebuffer *fb,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue