Beispiel #1
0
/**
 * drm_plane_helper_check_update() - Check plane update for validity
 * @plane: plane object to update
 * @crtc: owning CRTC of owning plane
 * @fb: framebuffer to flip onto plane
 * @src: source coordinates in 16.16 fixed point
 * @dest: integer destination coordinates
 * @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?
 * @visible: output parameter indicating whether plane is still visible after
 *           clipping
 *
 * Checks that a desired plane update is valid.  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_update(struct drm_plane *plane,
				    struct drm_crtc *crtc,
				    struct drm_framebuffer *fb,
				    struct drm_rect *src,
				    struct drm_rect *dest,
				    const struct drm_rect *clip,
				    int min_scale,
				    int max_scale,
				    bool can_position,
				    bool can_update_disabled,
				    bool *visible)
{
	int hscale, vscale;

	if (!fb) {
		*visible = false;
		return 0;
	}

	/* 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;
	}

	/* 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);
	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;
}
/**
 * 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 = drm_plane_state_src(state);
	*dst = drm_plane_state_dest(state);

	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;
}