compositor: Implement buffer transformation

Implement the wl_surface.set_buffer_transform request. This includes
tracking the double-buffered buffer transformation parameter and making
the gl renderer able to handle transformed buffers.
diff --git a/src/compositor.c b/src/compositor.c
index 6eb0b8c..44cd4a8 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -245,6 +245,8 @@
 	pixman_region32_init(&surface->texture_damage);
 
 	surface->buffer = NULL;
+	surface->buffer_transform = WL_OUTPUT_TRANSFORM_NORMAL;
+	surface->pending.buffer_transform = surface->buffer_transform;
 	surface->output = NULL;
 	surface->plane = &compositor->primary_plane;
 
@@ -653,6 +655,34 @@
 		return 0;
 }
 
+WL_EXPORT int32_t
+weston_surface_buffer_width(struct weston_surface *surface)
+{
+	switch (surface->buffer_transform) {
+	case WL_OUTPUT_TRANSFORM_90:
+	case WL_OUTPUT_TRANSFORM_270:
+	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+		return surface->buffer->height;
+	default:
+		return surface->buffer->width;
+	}
+}
+
+WL_EXPORT int32_t
+weston_surface_buffer_height(struct weston_surface *surface)
+{
+	switch (surface->buffer_transform) {
+	case WL_OUTPUT_TRANSFORM_90:
+	case WL_OUTPUT_TRANSFORM_270:
+	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+		return surface->buffer->width;
+	default:
+		return surface->buffer->height;
+	}
+}
+
 WL_EXPORT uint32_t
 weston_compositor_get_time(void)
 {
@@ -1237,6 +1267,31 @@
 	}
 }
 
+static int
+surface_pending_buffer_has_different_size(struct weston_surface *surface)
+{
+	int width, height;
+
+	switch (surface->pending.buffer_transform) {
+	case WL_OUTPUT_TRANSFORM_90:
+	case WL_OUTPUT_TRANSFORM_270:
+	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+		height = surface->pending.buffer->width;
+		width = surface->pending.buffer->height;
+		break;
+	default:
+		width = surface->pending.buffer->width;
+		height = surface->pending.buffer->height;
+	}
+
+	if (width == surface->geometry.width &&
+	    height == surface->geometry.height)
+		return 0;
+	else
+		return 1;
+}
+
 static void
 surface_commit(struct wl_client *client, struct wl_resource *resource)
 {
@@ -1245,10 +1300,12 @@
 
 	if (surface->pending.sx || surface->pending.sy ||
 	    (surface->pending.buffer &&
-	     (surface->pending.buffer->width != surface->geometry.width ||
-	      surface->pending.buffer->height != surface->geometry.height)))
+	     surface_pending_buffer_has_different_size(surface)))
 		surface->geometry.dirty = 1;
 
+	/* wl_surface.set_buffer_rotation */
+	surface->buffer_transform = surface->pending.buffer_transform;
+
 	/* wl_surface.attach */
 	if (surface->pending.buffer || surface->pending.remove_contents)
 		weston_surface_attach(surface, surface->pending.buffer);
@@ -1298,6 +1355,15 @@
 	weston_surface_schedule_repaint(surface);
 }
 
+static void
+surface_set_buffer_transform(struct wl_client *client,
+			     struct wl_resource *resource, int transform)
+{
+	struct weston_surface *surface = resource->data;
+
+	surface->pending.buffer_transform = transform;
+}
+
 static const struct wl_surface_interface surface_interface = {
 	surface_destroy,
 	surface_attach,
@@ -1305,7 +1371,8 @@
 	surface_frame,
 	surface_set_opaque_region,
 	surface_set_input_region,
-	surface_commit
+	surface_commit,
+	surface_set_buffer_transform
 };
 
 static void