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
@ -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 New Issue
Block a user