diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-02-12 11:33:45 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-02-12 14:26:21 +0000 |
commit | 607737cc47788e2a8896fddfece907a3cfb24f7f (patch) | |
tree | ab6f502a99808dbc7bd61a0eaba7b1ae1d69c707 | |
parent | 3b43630f5525a60e935dbc46e70354bb45444814 (diff) |
sna: Support native primary plane rotations
Use the display hardware for simple rotations, when exported through the
rotation property on the CRTC.
As the kernel support is not yet merged upstream, the feature is hidden
behind --enable-rotation.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | configure.ac | 11 | ||||
-rw-r--r-- | src/sna/gen5_render.c | 19 | ||||
-rw-r--r-- | src/sna/sna_display.c | 133 |
3 files changed, 159 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac index ea7473e1..4f73ba46 100644 --- a/configure.ac +++ b/configure.ac @@ -578,6 +578,17 @@ if test "x$CREATE2" = "xyes"; then xp_msg="$xp_msg create2" fi +AC_ARG_ENABLE(rotation, + AS_HELP_STRING([--enable-rotation], + [Enable use of native rotations (experimental) [default=no]]), + [ROTATION="$enableval"], + [ROTATION="no"]) +AM_CONDITIONAL(USE_ROTATION, test "x$ROTATION" = "xyes") +if test "x$ROTATION" = "xyes"; then + AC_DEFINE(USE_ROTATION,1,[Assume "rotation" support]) + xp_msg="$xp_msg rotation" +fi + AC_ARG_ENABLE(userptr, AS_HELP_STRING([--enable-userptr], [Enable use of userptr (experimental) [default=no]]), diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c index a89d31a3..c5ccaaca 100644 --- a/src/sna/gen5_render.c +++ b/src/sna/gen5_render.c @@ -1537,6 +1537,25 @@ gen5_composite_picture(struct sna *sna, return sna_render_picture_extract(sna, picture, channel, x, y, w, h, dst_x, dst_y); + DBG(("%s: pixmap, repeat=%d, filter=%d, transform?=%d [affine? %d], format=%08x\n", + __FUNCTION__, + channel->repeat, channel->filter, + channel->transform != NULL, channel->is_affine, + channel->pict_format)); + if (channel->transform) { + DBG(("%s: transform=[%f %f %f, %f %f %f, %f %f %f]\n", + __FUNCTION__, + channel->transform->matrix[0][0] / 65536., + channel->transform->matrix[0][1] / 65536., + channel->transform->matrix[0][2] / 65536., + channel->transform->matrix[1][0] / 65536., + channel->transform->matrix[1][1] / 65536., + channel->transform->matrix[1][2] / 65536., + channel->transform->matrix[2][0] / 65536., + channel->transform->matrix[2][1] / 65536., + channel->transform->matrix[2][2] / 65536.)); + } + return sna_render_pixmap_bo(sna, channel, pixmap, x, y, w, h, dst_x, dst_y); } diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index a6e6f686..9b05f740 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -105,6 +105,10 @@ struct sna_crtc { uint8_t id; uint8_t pipe; uint8_t plane; + + uint32_t rotation_id; + uint32_t supported_rotations; + uint32_t rotation, last_rotation; }; struct sna_property { @@ -842,10 +846,35 @@ sna_crtc_apply(xf86CrtcPtr crtc) int output_count = 0; int i; - DBG(("%s\n", __FUNCTION__)); + DBG(("%s CRTC:%d [pipe=%d]\n", __FUNCTION__, sna_crtc->id, sna_crtc->pipe)); assert(config->num_output < ARRAY_SIZE(output_ids)); + if (sna_crtc->rotation != sna_crtc->last_rotation) { + assert(sna_crtc->rotation_id); + + DBG(("%s: disabling CRTC:%d [pipe=%d] before changing rotation from %x to %x\n", + __FUNCTION__, sna_crtc->id, sna_crtc->pipe, + sna_crtc->last_rotation, sna_crtc->rotation)); + + memset(&arg, 0, sizeof(arg)); + arg.crtc_id = sna_crtc->id; + (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg); + + if (drmModeObjectSetProperty(sna->kgem.fd, sna_crtc->id, + DRM_MODE_OBJECT_CRTC, + sna_crtc->rotation_id, + sna_crtc->rotation)) { + ERR(("%s: set-rotation failed (rotation-id=%d, rotation=%d) on CRTC:%d [pipe=%d], errno=%d\n", + __FUNCTION__, sna_crtc->rotation_id, sna_crtc->rotation, sna_crtc->id, sna_crtc->pipe, errno)); + return false; + } + + sna_crtc->last_rotation = sna_crtc->rotation; + DBG(("%s: CRTC:%d [pipe=%d] rotation set to %x\n", + __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna_crtc->rotation)); + } + for (i = 0; i < config->num_output; i++) { xf86OutputPtr output = config->output[i]; @@ -1101,6 +1130,15 @@ sna_crtc_disable(xf86CrtcPtr crtc) arg.crtc_id = sna_crtc->id; (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg); + if (sna_crtc->last_rotation != RR_Rotate_0) { + assert(sna_crtc->rotation_id); + (void)drmModeObjectSetProperty(sna->kgem.fd, sna_crtc->id, + DRM_MODE_OBJECT_CRTC, + sna_crtc->rotation_id, + RR_Rotate_0); + sna_crtc->last_rotation = RR_Rotate_0; + } + sna_crtc_disable_shadow(sna, sna_crtc); if (sna_crtc->bo) { @@ -1333,8 +1371,19 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc) &crtc_to_fb, &f_crtc_to_fb, &f_fb_to_crtc)) { - DBG(("%s: RandR transform present\n", __FUNCTION__)); - return true; + bool needs_transform = true; + DBG(("%s: natively supported rotation? rotation=%x & supported=%x == %d\n", + __FUNCTION__, crtc->rotation, to_sna_crtc(crtc)->supported_rotations, + !!(crtc->rotation & to_sna_crtc(crtc)->supported_rotations))); + if (to_sna_crtc(crtc)->supported_rotations & crtc->rotation) + needs_transform = RRTransformCompute(crtc->x, crtc->y, + crtc->mode.HDisplay, crtc->mode.VDisplay, + RR_Rotate_0, transform, + NULL, NULL, NULL); + if (needs_transform) { + DBG(("%s: RandR transform present\n", __FUNCTION__)); + return true; + } } /* And finally check that it is entirely visible */ @@ -1365,6 +1414,8 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc) struct kgem_bo *bo; sna_crtc->transform = false; + sna_crtc->rotation = RR_Rotate_0; + if (sna_crtc->scanout_pixmap) { DBG(("%s: attaching to scanout pixmap\n", __FUNCTION__)); @@ -1468,6 +1519,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc) return NULL; assert(!sna_crtc->shadow); + sna_crtc->rotation = crtc->rotation; return kgem_bo_reference(bo); } } @@ -1913,6 +1965,77 @@ sna_crtc_find_plane(struct sna *sna, int pipe) #endif } +static void +sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *sna_crtc) +{ + drmModeObjectPropertiesPtr props; + + sna_crtc->supported_rotations = RR_Rotate_0; + sna_crtc->rotation = sna_crtc->last_rotation = RR_Rotate_0; + +#if USE_ROTATION + props = drmModeObjectGetProperties(sna->kgem.fd, + sna_crtc->id, + DRM_MODE_OBJECT_CRTC); + if (props) { + int i, j; + + DBG(("%s: CRTC:%d has %d props\n", __FUNCTION__, sna_crtc->id, props->count_props)); + + for (i = 0; i < props->count_props; i++) { + struct drm_mode_get_property prop; + struct drm_mode_property_enum *enums; + + memset(&prop, 0, sizeof(prop)); + prop.prop_id = props->props[i]; + if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) + continue; + + DBG(("%s: prop[%d] .id=%d, .name=%s, .flags=%x, .value=%ld\n", __FUNCTION__, i, + props->props[i], prop.name, prop.flags, props->prop_values[i])); + if ((prop.flags & DRM_MODE_PROP_BITMASK) == 0) + continue; + + if (strcmp(prop.name, "rotation")) + continue; + + /* Note that this property only controls the primary + * plane, not the cursor or sprite planes. + */ + sna_crtc->rotation_id = props->props[i]; + sna_crtc->rotation = sna_crtc->last_rotation = props->prop_values[i]; + + DBG(("%s: found rotation property .id=%d, num_enums=%d\n", + __FUNCTION__, prop.prop_id, prop.count_enum_blobs)); + enums = malloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)); + if (enums != NULL) { + prop.count_values = 0; + prop.enum_blob_ptr = (uintptr_t)enums; + + if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop) == 0) { + /* XXX we assume that the mapping between kernel enum and + * RandR remains fixed for our lifetimes. + */ + for (j = 0; j < prop.count_enum_blobs; j++) { + DBG(("%s: CRTC:%d rotation[%d] = %s [%x]\n", __FUNCTION__, sna_crtc->id, j, + enums[j].name, enums[j].value)); + sna_crtc->supported_rotations |= 1 << enums[j].value; + } + } + + free(enums); + } + + break; + } + + drmModeFreeObjectProperties(props); + } +#endif + DBG(("%s: CRTC:%d [pipe=%d], supported-rotations=%x, current-rotation=%x\n", + __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna_crtc->supported_rotations, sna_crtc->last_rotation)); +} + static bool sna_crtc_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num) { @@ -1921,7 +2044,7 @@ sna_crtc_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num) struct sna_crtc *sna_crtc; struct drm_i915_get_pipe_from_crtc_id get_pipe; - DBG(("%s\n", __FUNCTION__)); + DBG(("%s(%d)\n", __FUNCTION__, num)); sna_crtc = calloc(sizeof(struct sna_crtc), 1); if (sna_crtc == NULL) @@ -1963,6 +2086,8 @@ sna_crtc_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num) DBG(("%s: created handle=%d for cursor on CRTC:%d\n", __FUNCTION__, sna_crtc->cursor, sna_crtc->id)); + sna_crtc_init__rotation(sna, sna_crtc); + crtc->driver_private = sna_crtc; DBG(("%s: attached crtc[%d] id=%d, pipe=%d\n", __FUNCTION__, num, sna_crtc->id, sna_crtc->pipe)); |