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