summaryrefslogtreecommitdiff
path: root/src/sna/sna_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sna/sna_display.c')
-rw-r--r--src/sna/sna_display.c133
1 files changed, 129 insertions, 4 deletions
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));