[PATCH RFC] drm: support for rotated scanout

Rob Clark rob.clark at linaro.org
Mon Apr 2 08:31:47 PDT 2012


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


More information about the dri-devel mailing list