xserver-xorg-video-intel: Changes to 'ubuntu-trusty'
debian/changelog | 11
debian/patches/01-support-native-rotations.diff | 269 ++++
debian/patches/02-extend-native-rotation-to-sprites.diff | 407 +++++++
debian/patches/03-reorganise-native-rotation.diff | 245 ++++
debian/patches/04-inherit-native-rotation.diff | 21
debian/patches/05-clear-transform-on-disable.diff | 33
debian/patches/06-set-color-key-once.diff | 79 +
debian/patches/07-show-sprites-on-all-outputs.diff | 730 ++++++++++++
debian/patches/08-rewrite-rotation-universal-planes.diff | 856 +++++++++++++++
debian/patches/09-reduce-reflections-onto-rotations.diff | 90 +
debian/patches/10-handle-rotated-slaves.diff | 410 +++++++
debian/patches/series | 11
12 files changed, 3158 insertions(+), 4 deletions(-)
New commits:
commit dc762db1e2d7b45b080889131fb362aead003e87
Author: Maarten Lankhorst <maarten.lankhorst@ubuntu.com>
Date: Wed Oct 29 16:14:32 2014 +0100
add patch series for rotation support
diff --git a/debian/changelog b/debian/changelog
index 7fa7a26..dfa91b4 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,9 @@
-xserver-xorg-video-intel (2:2.99.910-0ubuntu1.2) UNRELEASED; urgency=low
+xserver-xorg-video-intel (2:2.99.910-0ubuntu1.2) UNRELEASED; urgency=medium
* Fix black screen with SNA. (LP: #1365695)
+ * Prevent crash when using SNA with fglrx.
+ - disable-outputs-when-slaved.patch
+ * Backport support for rotation with SNA. (LP: #1386620)
-- Maarten Lankhorst <maarten.lankhorst@ubuntu.com> Mon, 22 Sep 2014 11:26:22 +0200
diff --git a/debian/patches/01-support-native-rotations.diff b/debian/patches/01-support-native-rotations.diff
new file mode 100644
index 0000000..99b5144
--- /dev/null
+++ b/debian/patches/01-support-native-rotations.diff
@@ -0,0 +1,269 @@
+commit 607737cc47788e2a8896fddfece907a3cfb24f7f
+Author: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Wed Feb 12 11:33:45 2014 +0000
+
+ 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>
+
+diff --git a/configure.ac b/configure.ac
+index ea7473e..4f73ba4 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 a89d31a..c5ccaac 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 a6e6f68..9b05f74 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));
diff --git a/debian/patches/02-extend-native-rotation-to-sprites.diff b/debian/patches/02-extend-native-rotation-to-sprites.diff
new file mode 100644
index 0000000..87ab2d5
--- /dev/null
+++ b/debian/patches/02-extend-native-rotation-to-sprites.diff
@@ -0,0 +1,407 @@
+commit 135da294106f7158bb68eeeb9e6c171bcddd94f3
+Author: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu Feb 13 11:58:15 2014 +0000
+
+ sna: Extend native rotation support to sprites
+
+ The sprite plane can be independently rotated to the CRTC primary plane.
+ To rotate the sprite plane, we just set a property on the plane similar
+ to how we rotate the CRTC, so we can refactor them together to use the
+ same routines.
+
+ Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+
+diff --git a/src/sna/sna.h b/src/sna/sna.h
+index 7833095..7dc5067 100644
+--- a/src/sna/sna.h
++++ b/src/sna/sna.h
+@@ -439,8 +439,9 @@ static inline void sna_dri_close(struct sna *sna, ScreenPtr pScreen) { }
+ #endif
+ void sna_dri_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap);
+
++extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation);
+ extern int sna_crtc_to_pipe(xf86CrtcPtr crtc);
+-extern uint32_t sna_crtc_to_plane(xf86CrtcPtr crtc);
++extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc);
+ extern uint32_t sna_crtc_id(xf86CrtcPtr crtc);
+
+ CARD32 sna_format_for_depth(int depth);
+diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
+index 5c0a5a3..e123f48 100644
+--- a/src/sna/sna_display.c
++++ b/src/sna/sna_display.c
+@@ -93,22 +93,29 @@ union compat_mode_get_connector{
+
+ extern XF86ConfigPtr xf86configptr;
+
++struct rotation {
++ uint32_t obj_id, obj_type;
++ uint32_t prop_id;
++ uint32_t supported;
++ uint32_t current;
++};
++
+ struct sna_crtc {
+ struct drm_mode_modeinfo kmode;
+ int dpms_mode;
+ PixmapPtr scanout_pixmap;
+ struct kgem_bo *bo, *shadow_bo;
+ uint32_t cursor;
++ uint32_t sprite;
+ bool shadow;
+ bool fallback_shadow;
+ bool transform;
+ uint8_t id;
+ uint8_t pipe;
+- uint8_t plane;
+
+- uint32_t rotation_id;
+- uint32_t supported_rotations;
+- uint32_t rotation, last_rotation;
++ uint32_t rotation;
++ struct rotation primary_rotation;
++ struct rotation sprite_rotation;
+ };
+
+ struct sna_property {
+@@ -199,9 +206,9 @@ int sna_crtc_to_pipe(xf86CrtcPtr crtc)
+ return to_sna_crtc(crtc)->pipe;
+ }
+
+-uint32_t sna_crtc_to_plane(xf86CrtcPtr crtc)
++uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc)
+ {
+- return to_sna_crtc(crtc)->plane;
++ return to_sna_crtc(crtc)->sprite;
+ }
+
+ #ifndef NDEBUG
+@@ -862,6 +869,43 @@ sna_crtc_force_outputs_off(xf86CrtcPtr crtc)
+ }
+
+ static bool
++rotation_set(struct sna *sna, struct rotation *r, uint32_t desired)
++{
++ if (desired == r->current)
++ return true;
++
++ if ((desired & r->supported) == 0)
++ return false;
++
++ DBG(("%s: obj=%d, type=%u set-rotation=%x\n",
++ __FUNCTION__, r->obj_id, r->obj_type, desired));
++
++ assert(r->obj_id);
++ assert(r->obj_type);
++ assert(r->prop_id);
++
++ if (drmModeObjectSetProperty(sna->kgem.fd,
++ r->obj_id, r->obj_type,
++ r->prop_id, desired))
++ return false;
++
++ r->current = desired;
++ return true;
++}
++
++bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation)
++{
++ DBG(("%s: CRTC:%d [pipe=%d], sprite=%u set-rotation=%x\n",
++ __FUNCTION__,
++ to_sna_crtc(crtc)->id, to_sna_crtc(crtc)->pipe, to_sna_crtc(crtc)->sprite,
++ rotation));
++
++ return rotation_set(to_sna(crtc->scrn),
++ &to_sna_crtc(crtc)->sprite_rotation,
++ rotation);
++}
++
++static bool
+ sna_crtc_apply(xf86CrtcPtr crtc)
+ {
+ struct sna *sna = to_sna(crtc->scrn);
+@@ -876,30 +920,13 @@ sna_crtc_apply(xf86CrtcPtr crtc)
+
+ 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));
++ if (!rotation_set(sna, &sna_crtc->primary_rotation, sna_crtc->rotation)) {
++ ERR(("%s: set-primary-rotation failed (rotation-id=%d, rotation=%d) on CRTC:%d [pipe=%d], errno=%d\n",
++ __FUNCTION__, sna_crtc->primary_rotation.prop_id, sna_crtc->rotation, sna_crtc->id, sna_crtc->pipe, errno));
++ return false;
+ }
++ DBG(("%s: CRTC:%d [pipe=%d] primary 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];
+@@ -1156,14 +1183,7 @@ 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;
+- }
++ rotation_set(sna, &sna_crtc->primary_rotation, RR_Rotate_0);
+
+ sna_crtc_disable_shadow(sna, sna_crtc);
+
+@@ -1399,9 +1419,9 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc)
+ &f_fb_to_crtc)) {
+ 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)
++ __FUNCTION__, crtc->rotation, to_sna_crtc(crtc)->primary_rotation.supported,
++ !!(crtc->rotation & to_sna_crtc(crtc)->primary_rotation.supported)));
++ if (to_sna_crtc(crtc)->primary_rotation.supported & crtc->rotation)
+ needs_transform = RRTransformCompute(crtc->x, crtc->y,
+ crtc->mode.HDisplay, crtc->mode.VDisplay,
+ RR_Rotate_0, transform,
+@@ -1545,6 +1565,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
+ return NULL;
+
+ assert(!sna_crtc->shadow);
++ assert(sna_crtc->primary_rotation.supported & crtc->rotation);
+ sna_crtc->rotation = crtc->rotation;
+ return kgem_bo_reference(bo);
+ }
+@@ -1944,7 +1965,7 @@ static const xf86CrtcFuncsRec sna_crtc_funcs = {
+ };
+
+ static int
+-sna_crtc_find_plane(struct sna *sna, int pipe)
++sna_crtc_find_sprite(struct sna *sna, int pipe)
+ {
+ #ifdef DRM_IOCTL_MODE_GETPLANERESOURCES
+ struct drm_mode_get_plane_res r;
+@@ -1992,74 +2013,93 @@ sna_crtc_find_plane(struct sna *sna, int pipe)
+ }
+
+ static void
+-sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *sna_crtc)
++rotation_init(struct sna *sna, struct rotation *r, uint32_t obj_id, uint32_t obj_type)
+ {
++#if USE_ROTATION
+ drmModeObjectPropertiesPtr props;
++ int i, j;
+
+- 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;
++ props = drmModeObjectGetProperties(sna->kgem.fd, obj_id, obj_type);
++ if (props == NULL)
++ return;
+
+- DBG(("%s: CRTC:%d has %d props\n", __FUNCTION__, sna_crtc->id, props->count_props));
++ DBG(("%s: object %d (type %u) has %d props\n", __FUNCTION__,
++ obj_id, obj_type, props->count_props));
+
+- for (i = 0; i < props->count_props; i++) {
+- struct drm_mode_get_property prop;
+- struct drm_mode_property_enum *enums;
++ 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;
++ 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;
++ 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;
++ 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;
+- }
++ r->obj_id = obj_id;
++ r->obj_type = obj_type;
++ r->prop_id = props->props[i];
++ r->current = props->prop_values[i];
++
++ DBG(("%s: found rotation property .id=%d, value=%ld, num_enums=%d\n",
++ __FUNCTION__, prop.prop_id, (long)props->prop_values[i], 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: rotation[%d] = %s [%x]\n", __FUNCTION__,
++ j, enums[j].name, enums[j].value));
++ r->supported |= 1 << enums[j].value;
+ }
+-
+- free(enums);
+ }
+
+- break;
++ free(enums);
+ }
+
+- drmModeFreeObjectProperties(props);
++ 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 void
++rotation_reset(struct rotation *r)
++{
++ if (r->prop_id == 0)
++ return;
++
++ r->current = 0;
++}
++
++static void
++sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *sna_crtc)
++{
++ sna_crtc->rotation = RR_Rotate_0;
++ sna_crtc->primary_rotation.supported = RR_Rotate_0;
++ sna_crtc->primary_rotation.current = RR_Rotate_0;
++ sna_crtc->sprite_rotation = sna_crtc->primary_rotation;
++
++ rotation_init(sna, &sna_crtc->primary_rotation, sna_crtc->id, DRM_MODE_OBJECT_CRTC);
++ rotation_init(sna, &sna_crtc->sprite_rotation, sna_crtc->sprite, DRM_MODE_OBJECT_PLANE);
++
++ DBG(("%s: CRTC:%d [pipe=%d], primary: supported-rotations=%x, current-rotation=%x, sprite: supported-rotations=%x, current-rotation=%x\n",
++ __FUNCTION__, sna_crtc->id, sna_crtc->pipe,
++ sna_crtc->primary_rotation.supported, sna_crtc->primary_rotation.current,
++ sna_crtc->sprite_rotation.supported, sna_crtc->sprite_rotation.current));
+ }
+
+ static bool
+@@ -2089,7 +2129,7 @@ sna_crtc_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
+ return false;
+ }
+ sna_crtc->pipe = get_pipe.pipe;
+- sna_crtc->plane = sna_crtc_find_plane(sna, sna_crtc->pipe);
++ sna_crtc->sprite = sna_crtc_find_sprite(sna, sna_crtc->pipe);
+
+ if (xf86IsEntityShared(scrn->entityList[0]) &&
+ scrn->confScreen->device->screen != sna_crtc->pipe) {
+@@ -4316,6 +4356,10 @@ void sna_mode_reset(struct sna *sna)
+ continue;
+
+ sna_crtc->dpms_mode = DPMSModeOff;
++
++ /* Force the rotation property to be reset on next use */
++ rotation_reset(&sna_crtc->primary_rotation);
++ rotation_reset(&sna_crtc->sprite_rotation);
+ }
+
+ for (i = 0; i < config->num_output; i++) {
+diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c
+index b6a7950..f4dcb82 100644
+--- a/src/sna/sna_video_sprite.c
++++ b/src/sna/sna_video_sprite.c
+@@ -205,10 +205,10 @@ sna_video_sprite_show(struct sna *sna,
+ /* XXX handle video spanning multiple CRTC */
+
+ VG_CLEAR(s);
+- s.plane_id = sna_crtc_to_plane(crtc);
++ s.plane_id = sna_crtc_to_sprite(crtc);
+
+ update_dst_box_to_crtc_coords(sna, crtc, dstBox);
+- if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
++ if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
+ int tmp = frame->width;
+ frame->width = frame->height;
+ frame->height = tmp;
+@@ -383,11 +383,15 @@ static int sna_video_sprite_put_image(ClientPtr client,
+ &clip))
+ goto invisible;
+
+- if (!crtc || sna_crtc_to_plane(crtc) == 0)
++ if (!crtc || sna_crtc_to_sprite(crtc) == 0)
+ goto invisible;
+
+- /* sprites can't handle rotation natively, store it for the copy func */
+- video->rotation = crtc->rotation;
++ /* if sprite can't handle rotation natively, store it for the copy func */
++ video->rotation = RR_Rotate_0;
++ if (!sna_crtc_set_sprite_rotation(crtc, crtc->rotation)) {
++ sna_crtc_set_sprite_rotation(crtc, RR_Rotate_0);
++ video->rotation = crtc->rotation;
++ }
+
+ if (xvmc_passthrough(format->id)) {
+ DBG(("%s: using passthough, name=%d\n",
diff --git a/debian/patches/03-reorganise-native-rotation.diff b/debian/patches/03-reorganise-native-rotation.diff
new file mode 100644
index 0000000..ebcf23d
--- /dev/null
+++ b/debian/patches/03-reorganise-native-rotation.diff
@@ -0,0 +1,245 @@
+commit 5f8714335729b4fbbb33d89dbaf0f13aa3d8427b
+Author: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Fri Feb 14 16:18:34 2014 +0000
+
+ sna: Reorganise native rotation ioctls to compile on old Linux
+
+ It is not just the BSDs that lack these ioctls in their userspace
+ headers, but everything older than about a year...
+
+ Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+
+--- a/src/sna/sna_display.c
++++ b/src/sna/sna_display.c
+@@ -842,9 +842,109 @@
+ to_sna_crtc(crtc)->dpms_mode = DPMSModeOff;
+ }
+
++#define LOCAL_MODE_OBJECT_CRTC 0xcccccccc
++#define LOCAL_MODE_OBJECT_PLANE 0xeeeeeeee
++static void
++rotation_init(struct sna *sna, struct rotation *r, uint32_t obj_id, uint32_t obj_type)
++{
++#if USE_ROTATION
++#define LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct local_mode_obj_get_properties)
++ struct local_mode_obj_get_properties {
++ uint64_t props_ptr;
++ uint64_t prop_values_ptr;
++ uint32_t count_props;
++ uint32_t obj_id;
++ uint32_t obj_type;
++ uint32_t pad;
++ } props;
++ uint64_t *prop_values;
++ int i, j;
++
++ memset(&props, 0, sizeof(struct local_mode_obj_get_properties));
++ props.obj_id = obj_id;
++ props.obj_type = obj_type;
++
++ if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES, &props))
++ return;
++
++ DBG(("%s: object %d (type %u) has %d props\n", __FUNCTION__,
++ obj_id, obj_type, props.count_props));
++
++ if (props.count_props == 0)
++ return;
++
++ prop_values = malloc(2*sizeof(uint64_t)*props.count_props);
++ if (prop_values == NULL)
++ return;
++
++ props.props_ptr = (uintptr_t)prop_values;
++ props.prop_values_ptr = (uintptr_t)(prop_values + props.count_props);
++
++ if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES, &props))
++ props.count_props = 0;
++
++ 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 = prop_values[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,
++ prop_values[i], prop.name, prop.flags, prop_values[i+props.count_props]));
++ if ((prop.flags & (1 << 5)) == 0)
++ continue;
++
++ if (strcmp(prop.name, "rotation"))
++ continue;
++
++ r->obj_id = obj_id;
++ r->obj_type = obj_type;
++ r->prop_id = prop_values[i];
++ r->current = prop_values[i + props.count_props];
++
++ DBG(("%s: found rotation property .id=%d, value=%ld, num_enums=%d\n",
++ __FUNCTION__, prop.prop_id, (long)prop_values[i+props.count_props], 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: rotation[%d] = %s [%x]\n", __FUNCTION__,
++ j, enums[j].name, enums[j].value));
++ r->supported |= 1 << enums[j].value;
++ }
++ }
++
++ free(enums);
++ }
++
++ break;
++ }
++
++ free(prop_values);
++#endif
++}
++
+ static bool
+ rotation_set(struct sna *sna, struct rotation *r, uint32_t desired)
+ {
++#define LOCAL_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct local_mode_obj_set_property)
++ struct local_mode_obj_set_property {
++ uint64_t value;
++ uint32_t prop_id;
++ uint32_t obj_id;
++ uint32_t obj_type;
++ uint32_t pad;
++ } prop;
++
+ if (desired == r->current)
+ return true;
+
+@@ -858,15 +958,27 @@
+ assert(r->obj_type);
+ assert(r->prop_id);
+
+- if (drmModeObjectSetProperty(sna->kgem.fd,
+- r->obj_id, r->obj_type,
+- r->prop_id, desired))
++ prop.obj_id = r->obj_id;
++ prop.obj_type = r->obj_type;
++ prop.prop_id = r->prop_id;
++ prop.value = desired;
++
++ if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_SETPROPERTY, &prop))
+ return false;
+
+ r->current = desired;
+ return true;
+ }
+
++static void
++rotation_reset(struct rotation *r)
++{
++ if (r->prop_id == 0)
++ return;
++
++ r->current = 0;
++}
++
+ bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation)
+ {
+ DBG(("%s: CRTC:%d [pipe=%d], sprite=%u set-rotation=%x\n",
+@@ -1987,79 +2099,6 @@
+ }
+
+ static void
+-rotation_init(struct sna *sna, struct rotation *r, uint32_t obj_id, uint32_t obj_type)
+-{
+-#if USE_ROTATION
+- drmModeObjectPropertiesPtr props;
+- int i, j;
+-
+- props = drmModeObjectGetProperties(sna->kgem.fd, obj_id, obj_type);
+- if (props == NULL)
+- return;
+-
+- DBG(("%s: object %d (type %u) has %d props\n", __FUNCTION__,
+- obj_id, obj_type, 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;
+-
+- r->obj_id = obj_id;
+- r->obj_type = obj_type;
+- r->prop_id = props->props[i];
+- r->current = props->prop_values[i];
+-
+- DBG(("%s: found rotation property .id=%d, value=%ld, num_enums=%d\n",
+- __FUNCTION__, prop.prop_id, (long)props->prop_values[i], 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: rotation[%d] = %s [%x]\n", __FUNCTION__,
+- j, enums[j].name, enums[j].value));
+- r->supported |= 1 << enums[j].value;
+- }
+- }
+-
+- free(enums);
+- }
+-
+- break;
+- }
+-
+- drmModeFreeObjectProperties(props);
+-#endif
+-}
+-
+-static void
+-rotation_reset(struct rotation *r)
+-{
+- if (r->prop_id == 0)
+- return;
+-
+- r->current = 0;
+-}
+-
+-static void
+ sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *sna_crtc)
+ {
+ sna_crtc->rotation = RR_Rotate_0;
+@@ -2067,8 +2106,8 @@
+ sna_crtc->primary_rotation.current = RR_Rotate_0;
+ sna_crtc->sprite_rotation = sna_crtc->primary_rotation;
+
+- rotation_init(sna, &sna_crtc->primary_rotation, sna_crtc->id, DRM_MODE_OBJECT_CRTC);
+- rotation_init(sna, &sna_crtc->sprite_rotation, sna_crtc->sprite, DRM_MODE_OBJECT_PLANE);
++ rotation_init(sna, &sna_crtc->primary_rotation, sna_crtc->id, LOCAL_MODE_OBJECT_CRTC);
++ rotation_init(sna, &sna_crtc->sprite_rotation, sna_crtc->sprite, LOCAL_MODE_OBJECT_PLANE);
+
+ DBG(("%s: CRTC:%d [pipe=%d], primary: supported-rotations=%x, current-rotation=%x, sprite: supported-rotations=%x, current-rotation=%x\n",
+ __FUNCTION__, sna_crtc->id, sna_crtc->pipe,
diff --git a/debian/patches/04-inherit-native-rotation.diff b/debian/patches/04-inherit-native-rotation.diff
new file mode 100644
index 0000000..ea781d3
--- /dev/null
+++ b/debian/patches/04-inherit-native-rotation.diff
@@ -0,0 +1,21 @@
+commit 8eb6335653e6e38228ecf95c3eef82ca2a864e45
+Author: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Fri Feb 14 19:36:47 2014 +0000
+
+ sna: Inherit the native rotation on initial output probing
+
+ Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+
+diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
+index 8d2ec8a..636217a 100644
+--- a/src/sna/sna_display.c
++++ b/src/sna/sna_display.c
+@@ -3692,7 +3692,7 @@ static bool sna_probe_initial_configuration(struct sna *sna)
+ continue;
+
+ mode_from_kmode(scrn, &mode.mode, &crtc->desiredMode);
+- crtc->desiredRotation = RR_Rotate_0;
++ crtc->desiredRotation = sna_crtc->primary_rotation.current;
+ crtc->desiredX = mode.x;
Reply to: