[PATCH RFC] drm: support for rotated scanout
Rob Clark
rob.clark at linaro.org
Fri Mar 30 15:59:32 PDT 2012
From: Rob Clark <rob at ti.com>
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.
---
Note: RFC still mainly because I've only tested the CRTC rotation so
far.. still need to write some test code for plane rotation.
drivers/gpu/drm/drm_crtc.c | 50 +++++++++++++++++++++++++++++--------------
include/drm/drm_crtc.h | 9 ++++++++
2 files changed, 43 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 0dff444..261c9bd 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -375,6 +375,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);
@@ -609,6 +610,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
plane->base.properties = &plane->properties;
plane->dev = dev;
plane->funcs = funcs;
+ plane->invert_dimensions = false;
plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
GFP_KERNEL);
if (!plane->format_types) {
@@ -1758,6 +1760,9 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
fb_width = fb->width << 16;
fb_height = fb->height << 16;
+ if (plane->invert_dimensions)
+ swap(fb_width, fb_height);
+
/* Make sure source coordinates are inside the fb. */
if (plane_req->src_w > fb_width ||
plane_req->src_x > fb_width - plane_req->src_w ||
@@ -1856,6 +1861,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) {
@@ -1891,14 +1897,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;
}
@@ -3452,6 +3464,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 ||
@@ -3481,14 +3494,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;
}
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index b5017c9..78dd5b5 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -364,6 +364,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
@@ -397,6 +400,8 @@ struct drm_crtc {
*/
struct drm_display_mode hwmode;
+ bool invert_dimensions;
+
int x, y;
const struct drm_crtc_funcs *funcs;
@@ -636,6 +641,9 @@ struct drm_plane_funcs {
* @gamma_size: size of gamma table
* @gamma_store: gamma correction table
* @enabled: enabled flag
+ * @invert_dimensions: for purposes of error checking plane vs fb sizes,
+ * invert the width/height of the plane. This is used if the driver
+ * is performing 90 or 270 degree rotated scanout
* @funcs: helper functions
* @helper_private: storage for drver layer
*/
@@ -657,6 +665,7 @@ struct drm_plane {
uint16_t *gamma_store;
bool enabled;
+ bool invert_dimensions;
const struct drm_plane_funcs *funcs;
void *helper_private;
--
1.7.9.1
More information about the dri-devel
mailing list