On Sat, Mar 31, 2012 at 4:09 PM, Ville Syrj?l? <syrjala at sci.fi> wrote: > On Fri, Mar 30, 2012 at 05:59:32PM -0500, Rob Clark wrote: >> 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); >> + > > In my opinion the only sane way to specify this stuff is that > the source coordinates are not transformed in any way.
fwiw, it might be a bit odd that in one case I swapped fb dimensions, and in the other crtc dimensions.. although it was just laziness (there were fewer param's to swap that way ;-)) > So you fetch the data from the fb based on the source coordinates, then > apply all plane transformations (if any), and then apply all CRTC > transformations (if any). fwiw, in my case planes and CRTCs are rotated independently.. ie. rotating the CRTC doesn't automatically rotate the planes. But I include invert_dimensions flag in both drm_crtc and drm_plane so drivers for hw that works differently can do whatever is appropriate > >> ? ? ? /* 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)" >> : ""); > > I would perhaps just stick more details about the transformations into > drm_crtc, but we will anyway require a better mode setting API. So > perhaps this is an OK intermediate solution. > I was trying to avoid putting full matrix transformation in the kernel ;-) but at least the hw I'm familiar with is only doing simple isometric transformations in scanout (ie. multiples of 90 degress and/or horiz/vert mirroring). Anything more complex would require a shadow buffer and gpu, which is (I think) better to do in userspace. But I don't know if this is sufficient for other drivers or not.. part of the reason for the RFC ;-) BR, -R >> ? ? ? ? ? ? ? ? ? ? ? ret = -ENOSPC; >> ? ? ? ? ? ? ? ? ? ? ? goto out; >> ? ? ? ? ? ? ? } > > -- > Ville Syrj?l? > syrjala at sci.fi > http://www.sci.fi/~syrjala/ > _______________________________________________ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel