Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c80e128 authored by Rob Clark's avatar Rob Clark Committed by Dave Airlie
Browse files

drm: support for rotated scanout



For drivers that can support rotated scanout, the extra parameter
checking in drm-core, while nice, tends to get confused.  To solve
this drivers can set the crtc or plane invert_dimensions field so
that the dimension checking takes into account the rotation that
the driver is performing.

v1: original
v2: remove invert_dimensions from plane, at Ville's suggestion.
    Userspace can give rotated src coordinates, so invert_dimensions
    is not required for planes.

Signed-off-by: default avatarRob Clark <rob@ti.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent f7eff60e
Loading
Loading
Loading
Loading
+30 −16
Original line number Diff line number Diff line
@@ -437,6 +437,7 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,

	crtc->dev = dev;
	crtc->funcs = funcs;
	crtc->invert_dimensions = false;

	mutex_lock(&dev->mode_config.mutex);

@@ -1912,6 +1913,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);

	if (crtc_req->mode_valid) {
		int hdisplay, vdisplay;
		/* If we have a mode we need a framebuffer. */
		/* If we pass -1, set the mode with the currently bound fb */
		if (crtc_req->fb_id == -1) {
@@ -1947,14 +1949,20 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,

		drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);

		if (mode->hdisplay > fb->width ||
		    mode->vdisplay > fb->height ||
		    crtc_req->x > fb->width - mode->hdisplay ||
		    crtc_req->y > fb->height - mode->vdisplay) {
			DRM_DEBUG_KMS("Invalid CRTC viewport %ux%u+%u+%u for fb size %ux%u.\n",
				      mode->hdisplay, mode->vdisplay,
				      crtc_req->x, crtc_req->y,
				      fb->width, fb->height);
		hdisplay = mode->hdisplay;
		vdisplay = mode->vdisplay;

		if (crtc->invert_dimensions)
			swap(hdisplay, vdisplay);

		if (hdisplay > fb->width ||
		    vdisplay > fb->height ||
		    crtc_req->x > fb->width - hdisplay ||
		    crtc_req->y > fb->height - vdisplay) {
			DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
				      fb->width, fb->height,
				      hdisplay, vdisplay, crtc_req->x, crtc_req->y,
				      crtc->invert_dimensions ? " (inverted)" : "");
			ret = -ENOSPC;
			goto out;
		}
@@ -3546,6 +3554,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
	struct drm_framebuffer *fb;
	struct drm_pending_vblank_event *e = NULL;
	unsigned long flags;
	int hdisplay, vdisplay;
	int ret = -EINVAL;

	if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
@@ -3575,14 +3584,19 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
		goto out;
	fb = obj_to_fb(obj);

	if (crtc->mode.hdisplay > fb->width ||
	    crtc->mode.vdisplay > fb->height ||
	    crtc->x > fb->width - crtc->mode.hdisplay ||
	    crtc->y > fb->height - crtc->mode.vdisplay) {
		DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n",
			      fb->width, fb->height,
			      crtc->mode.hdisplay, crtc->mode.vdisplay,
			      crtc->x, crtc->y);
	hdisplay = crtc->mode.hdisplay;
	vdisplay = crtc->mode.vdisplay;

	if (crtc->invert_dimensions)
		swap(hdisplay, vdisplay);

	if (hdisplay > fb->width ||
	    vdisplay > fb->height ||
	    crtc->x > fb->width - hdisplay ||
	    crtc->y > fb->height - vdisplay) {
		DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
			      fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y,
			      crtc->invert_dimensions ? " (inverted)" : "");
		ret = -ENOSPC;
		goto out;
	}
+5 −0
Original line number Diff line number Diff line
@@ -368,6 +368,9 @@ struct drm_crtc_funcs {
 * @enabled: is this CRTC enabled?
 * @mode: current mode timings
 * @hwmode: mode timings as programmed to hw regs
 * @invert_dimensions: for purposes of error checking crtc vs fb sizes,
 *    invert the width/height of the crtc.  This is used if the driver
 *    is performing 90 or 270 degree rotated scanout
 * @x: x position on screen
 * @y: y position on screen
 * @funcs: CRTC control functions
@@ -401,6 +404,8 @@ struct drm_crtc {
	 */
	struct drm_display_mode hwmode;

	bool invert_dimensions;

	int x, y;
	const struct drm_crtc_funcs *funcs;