[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: