summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac11
-rw-r--r--src/sna/gen5_render.c19
-rw-r--r--src/sna/sna_display.c133
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));