--- ./mutter-3.26.2.orig/src/compositor/meta-shaped-texture.c	2017-10-05 21:10:45.000000000 +0200
+++ ./mutter-3.26.2/src/compositor/meta-shaped-texture.c	2017-12-08 18:46:08.742400917 +0100
@@ -92,8 +92,13 @@
   cairo_region_t *clip_region;
   cairo_region_t *unobscured_region;
 
+  /* Viewport stuff */
+  cairo_rectangle_int_t viewport_src_rect;
+  guint viewport_dest_width, viewport_dest_height;
+
   guint tex_width, tex_height;
   guint fallback_width, fallback_height;
+  guint dest_width, dest_height;
 
   guint create_mipmaps : 1;
 };
@@ -149,8 +154,8 @@
 
       if (priv->texture)
         {
-          width = priv->tex_width;
-          height = priv->tex_height;
+          width = priv->dest_width;
+          height = priv->dest_height;
         }
       else
         {
@@ -297,23 +302,44 @@
 }
 
 static void
+scale_coords_by_src (cairo_rectangle_int_t *coords,
+                     int dest_width, int dest_height,
+                     cairo_rectangle_int_t *src_rect)
+{
+  if (src_rect->width == 0 && src_rect->height == 0)
+    return;
+
+  coords->x      = ((coords->x      / dest_width)  * src_rect->width)  + src_rect->x;
+  coords->y      = ((coords->y      / dest_height) * src_rect->height) + src_rect->y;
+  coords->width  = ((coords->width  / dest_width)  * src_rect->width);
+  coords->height = ((coords->height / dest_height) * src_rect->height);
+}
+
+static void
 paint_clipped_rectangle (CoglFramebuffer       *fb,
                          CoglPipeline          *pipeline,
                          cairo_rectangle_int_t *rect,
-                         ClutterActorBox       *alloc)
+                         ClutterActorBox       *alloc,
+                         cairo_rectangle_int_t *src_rect)
 {
+  cairo_rectangle_int_t pixel_coords;
   float coords[8];
   float x1, y1, x2, y2;
+  float dest_width = alloc->x2 - alloc->x1;
+  float dest_height = alloc->y2 - alloc->y1;
 
   x1 = rect->x;
   y1 = rect->y;
   x2 = rect->x + rect->width;
   y2 = rect->y + rect->height;
 
-  coords[0] = rect->x / (alloc->x2 - alloc->x1);
-  coords[1] = rect->y / (alloc->y2 - alloc->y1);
-  coords[2] = (rect->x + rect->width) / (alloc->x2 - alloc->x1);
-  coords[3] = (rect->y + rect->height) / (alloc->y2 - alloc->y1);
+  pixel_coords = *rect;
+  scale_coords_by_src (&pixel_coords, dest_width, dest_height, src_rect);
+
+  coords[0] = pixel_coords.x / dest_width;
+  coords[1] = pixel_coords.y / dest_height;
+  coords[2] = (pixel_coords.x + pixel_coords.width) / dest_width;
+  coords[3] = (pixel_coords.y + pixel_coords.height) / dest_height;
 
   coords[4] = coords[0];
   coords[5] = coords[1];
@@ -326,6 +352,32 @@
 }
 
 static void
+update_size (MetaShapedTexture *stex)
+{
+  MetaShapedTexturePrivate *priv = stex->priv;
+  guint dest_width, dest_height;
+
+  if (priv->viewport_dest_width > 0)
+    dest_width = priv->viewport_dest_width;
+  else
+    dest_width = priv->tex_width;
+
+  if (priv->viewport_dest_height > 0)
+    dest_height = priv->viewport_dest_height;
+  else
+    dest_height = priv->tex_height;
+
+  if (priv->dest_width != dest_width ||
+      priv->dest_height != dest_height)
+    {
+      priv->dest_width = dest_width;
+      priv->dest_height = dest_height;
+      clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
+      g_signal_emit (stex, signals[SIZE_CHANGED], 0);
+    }
+}
+
+static void
 set_cogl_texture (MetaShapedTexture *stex,
                   CoglTexture       *cogl_tex)
 {
@@ -359,8 +411,7 @@
       priv->tex_width = width;
       priv->tex_height = height;
       meta_shaped_texture_set_mask_texture (stex, NULL);
-      clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
-      g_signal_emit (stex, signals[SIZE_CHANGED], 0);
+      update_size (stex);
     }
 
   /* NB: We don't queue a redraw of the actor here because we don't
@@ -377,7 +428,7 @@
 {
   MetaShapedTexture *stex = (MetaShapedTexture *) actor;
   MetaShapedTexturePrivate *priv = stex->priv;
-  guint tex_width, tex_height;
+  guint dest_width, dest_height;
   guchar opacity;
   CoglContext *ctx;
   CoglFramebuffer *fb;
@@ -414,13 +465,13 @@
   if (paint_tex == NULL)
     return;
 
-  tex_width = priv->tex_width;
-  tex_height = priv->tex_height;
+  dest_width = priv->dest_width;
+  dest_height = priv->dest_height;
 
-  if (tex_width == 0 || tex_height == 0) /* no contents yet */
+  if (dest_width == 0 || dest_height == 0) /* no contents yet */
     return;
 
-  cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
+  cairo_rectangle_int_t tex_rect = { 0, 0, dest_width, dest_height };
 
   /* Use nearest-pixel interpolation if the texture is unscaled. This
    * improves performance, especially with software rendering.
@@ -428,7 +479,7 @@
 
   filter = COGL_PIPELINE_FILTER_LINEAR;
 
-  if (meta_actor_painting_untransformed (tex_width, tex_height, NULL, NULL))
+  if (meta_actor_painting_untransformed (dest_width, dest_height, NULL, NULL))
     filter = COGL_PIPELINE_FILTER_NEAREST;
 
   ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
@@ -503,7 +554,7 @@
             {
               cairo_rectangle_int_t rect;
               cairo_region_get_rectangle (region, i, &rect);
-              paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
+              paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc, &priv->viewport_src_rect);
             }
         }
 
@@ -556,16 +607,13 @@
               if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
                 continue;
 
-              paint_clipped_rectangle (fb, blended_pipeline, &rect, &alloc);
+              paint_clipped_rectangle (fb, blended_pipeline, &rect, &alloc, &priv->viewport_src_rect);
             }
         }
       else
         {
           /* 3) blended_region is NULL. Do a full paint. */
-          cogl_framebuffer_draw_rectangle (fb, blended_pipeline,
-                                           0, 0,
-                                           alloc.x2 - alloc.x1,
-                                           alloc.y2 - alloc.y1);
+          paint_clipped_rectangle (fb, blended_pipeline, &tex_rect, &alloc, &priv->viewport_src_rect);
         }
     }
 
@@ -583,7 +631,7 @@
   guint width;
 
   if (priv->texture)
-    width = priv->tex_width;
+    width = priv->dest_width;
   else
     width = priv->fallback_width;
 
@@ -603,7 +651,7 @@
   guint height;
 
   if (priv->texture)
-    height = priv->tex_height;
+    height = priv->dest_height;
   else
     height = priv->fallback_height;
 
@@ -888,6 +936,22 @@
   return priv->opaque_region;
 }
 
+void
+meta_shaped_texture_set_viewport (MetaShapedTexture     *stex,
+                                  cairo_rectangle_int_t *src_rect,
+                                  int                    dest_width,
+                                  int                    dest_height)
+{
+  MetaShapedTexturePrivate *priv = stex->priv;
+
+  priv->viewport_src_rect = *src_rect;
+
+  priv->viewport_dest_width = dest_width;
+  priv->viewport_dest_height = dest_height;
+  update_size (stex);
+  clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
+}
+
 /**
  * meta_shaped_texture_get_image:
  * @stex: A #MetaShapedTexture
--- ./mutter-3.26.2.orig/src/compositor/meta-shaped-texture-private.h	2017-10-05 21:10:45.000000000 +0200
+++ ./mutter-3.26.2/src/compositor/meta-shaped-texture-private.h	2017-12-08 18:19:43.476284403 +0100
@@ -42,4 +42,8 @@
 gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
 cairo_region_t * meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex);
 
+void meta_shaped_texture_set_viewport (MetaShapedTexture     *stex,
+                                       cairo_rectangle_int_t *src_rect,
+                                       int                    dest_width,
+                                       int                    dest_height);
 #endif
--- ./mutter-3.26.2.orig/src/compositor/meta-surface-actor.c	2017-03-09 19:39:07.000000000 +0100
+++ ./mutter-3.26.2/src/compositor/meta-surface-actor.c	2017-12-08 18:16:54.904093577 +0100
@@ -242,6 +242,16 @@
   return meta_shaped_texture_get_opaque_region (priv->texture);
 }
 
+void
+meta_surface_actor_set_viewport (MetaSurfaceActor      *self,
+                                 cairo_rectangle_int_t *src_rect,
+                                 int                    dest_width,
+                                 int                    dest_height)
+{
+  MetaSurfaceActorPrivate *priv = self->priv;
+  meta_shaped_texture_set_viewport (priv->texture, src_rect, dest_width, dest_height);
+}
+
 static gboolean
 is_frozen (MetaSurfaceActor *self)
 {
--- ./mutter-3.26.2.orig/src/compositor/meta-surface-actor.h	2017-03-09 19:39:07.000000000 +0100
+++ ./mutter-3.26.2/src/compositor/meta-surface-actor.h	2017-12-08 16:49:31.838538471 +0100
@@ -62,6 +62,10 @@
                                            cairo_region_t   *region);
 cairo_region_t * meta_surface_actor_get_opaque_region (MetaSurfaceActor *self);
 
+void meta_surface_actor_set_viewport (MetaSurfaceActor      *self,
+                                      cairo_rectangle_int_t *src_rect,
+                                      int                    dest_width,
+                                      int                    dest_height);
 void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
                                         int x, int y, int width, int height);
 void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
--- ./mutter-3.26.2.orig/src/Makefile.am	2017-10-30 23:24:49.000000000 +0100
+++ ./mutter-3.26.2/src/Makefile.am	2017-12-08 17:48:28.273168155 +0100
@@ -82,6 +82,8 @@
 	linux-dmabuf-unstable-v1-server-protocol.h				\
 	keyboard-shortcuts-inhibit-unstable-v1-protocol.c		\
 	keyboard-shortcuts-inhibit-unstable-v1-server-protocol.h	\
+	viewporter-protocol.c                       			\
+	viewporter-server-protocol.h                			\
 	$(NULL)
 endif
 
--- ./mutter-3.26.2.orig/src/wayland/meta-wayland-surface.c	2017-10-30 23:24:54.000000000 +0100
+++ ./mutter-3.26.2/src/wayland/meta-wayland-surface.c	2017-12-08 18:12:42.645614428 +0100
@@ -44,6 +44,7 @@
 #include "meta-wayland-xdg-shell.h"
 #include "meta-wayland-wl-shell.h"
 #include "meta-wayland-gtk-shell.h"
+#include "viewporter-server-protocol.h"
 
 #include "meta-cursor-tracker-private.h"
 #include "display-private.h"
@@ -506,6 +507,7 @@
   state->has_new_geometry = FALSE;
   state->has_new_min_size = FALSE;
   state->has_new_max_size = FALSE;
+  state->viewport.changed = FALSE;
 }
 
 static void
@@ -863,6 +865,11 @@
             meta_wayland_surface_ref_buffer_use_count (surface);
         }
     }
+  if (pending->viewport.changed)
+    meta_surface_actor_set_viewport (surface->surface_actor,
+                                     &pending->viewport.src_rect,
+                                     pending->viewport.dest_width,
+                                     pending->viewport.dest_height);
 
 cleanup:
   /* If we have a buffer that we are not using, decrease the use count so it may
@@ -1724,6 +1731,122 @@
   wl_resource_set_implementation (resource, &meta_wayland_subcompositor_interface, data, NULL);
 }
 
+static void
+destroy_wl_viewport (struct wl_resource *resource)
+{
+  MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
+
+  surface->has_viewport = FALSE;
+  surface->pending->viewport.changed = TRUE;
+}
+
+static void
+wp_viewport_destroy (struct wl_client *client,
+                     struct wl_resource *resource)
+{
+  wl_resource_destroy (resource);
+}
+
+static void
+viewport_set_src (struct wl_resource *resource,
+                  wl_fixed_t src_x,
+                  wl_fixed_t src_y,
+                  wl_fixed_t src_width,
+                  wl_fixed_t src_height)
+{
+  MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
+  surface->pending->viewport.src_rect.x = wl_fixed_to_int (src_x);
+  surface->pending->viewport.src_rect.y = wl_fixed_to_int (src_y);
+  surface->pending->viewport.src_rect.width = wl_fixed_to_int (src_width);
+  surface->pending->viewport.src_rect.height = wl_fixed_to_int (src_height);
+  surface->pending->viewport.changed = TRUE;
+}
+
+static void
+viewport_set_dest (struct wl_resource *resource,
+                   int dst_width,
+                   int dst_height)
+{
+  MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
+  surface->pending->viewport.dest_width = dst_width;
+  surface->pending->viewport.dest_height = dst_height;
+  surface->pending->viewport.changed = TRUE;
+}
+
+static void
+wp_viewport_set_source (struct wl_client *client,
+                        struct wl_resource *resource,
+                        wl_fixed_t src_x,
+                        wl_fixed_t src_y,
+                        wl_fixed_t src_width,
+                        wl_fixed_t src_height)
+{
+  viewport_set_src (resource, src_x, src_y, src_width, src_height);
+}
+
+static void
+wp_viewport_set_destination (struct wl_client *client,
+                             struct wl_resource *resource,
+                             int dst_width,
+                             int dst_height)
+{
+  viewport_set_dest (resource, dst_width, dst_height);
+}
+
+static const struct wp_viewport_interface meta_wayland_viewport_interface = {
+  wp_viewport_destroy,
+  wp_viewport_set_source,
+  wp_viewport_set_destination,
+};
+
+static void
+wp_viewporter_destroy (struct wl_client *client,
+                   struct wl_resource *resource)
+{
+  wl_resource_destroy (resource);
+}
+
+static void
+wp_viewporter_get_viewport (struct wl_client *client,
+                        struct wl_resource *master_resource,
+                        uint32_t viewport_id,
+                        struct wl_resource *surface_resource)
+{
+  struct wl_resource *resource;
+  MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+
+  if (surface->has_viewport)
+    {
+      wl_resource_post_error (master_resource,
+                              WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS,
+                              "viewport already exists on surface");
+      return;
+    }
+
+  resource = wl_resource_create (client, &wp_viewport_interface, wl_resource_get_version (master_resource),
+viewport_id);
+  wl_resource_set_implementation (resource, &meta_wayland_viewport_interface, surface, destroy_wl_viewport);
+
+  surface->has_viewport = TRUE;
+}
+
+static const struct wp_viewporter_interface meta_wayland_scaler_interface = {
+  wp_viewporter_destroy,
+  wp_viewporter_get_viewport,
+};
+
+static void
+bind_scaler (struct wl_client *client,
+             void             *data,
+             guint32           version,
+             guint32           id)
+{
+  struct wl_resource *resource;
+
+  resource = wl_resource_create (client, &wp_viewporter_interface, version, id);
+  wl_resource_set_implementation (resource, &meta_wayland_scaler_interface, data, NULL);
+}
+
 void
 meta_wayland_shell_init (MetaWaylandCompositor *compositor)
 {
@@ -1736,6 +1859,12 @@
                         META_WL_SUBCOMPOSITOR_VERSION,
                         compositor, bind_subcompositor) == NULL)
     g_error ("Failed to register a global wl-subcompositor object");
+
+  if (wl_global_create (compositor->wayland_display,
+                        &wp_viewporter_interface,
+                        META_WL_SCALER_VERSION,
+                        compositor, bind_scaler) == NULL)
+    g_error ("Failed to register a global wl-subcompositor object");
 }
 
 void
--- ./mutter-3.26.2.orig/src/wayland/meta-wayland-surface.h	2017-10-05 19:06:58.000000000 +0200
+++ ./mutter-3.26.2/src/wayland/meta-wayland-surface.h	2017-12-08 17:00:56.491859409 +0100
@@ -152,6 +152,12 @@
   gboolean has_new_max_size;
   int new_max_width;
   int new_max_height;
+
+  struct {
+    gboolean changed;
+    cairo_rectangle_int_t src_rect;
+    int32_t dest_width, dest_height;
+  } viewport;
 };
 
 struct _MetaWaylandDragDestFuncs
@@ -186,6 +192,7 @@
   int32_t offset_x, offset_y;
   GList *subsurfaces;
   GHashTable *outputs_to_destroy_notify_id;
+  gboolean has_viewport;
 
   /* Buffer reference state. */
   struct {
--- ./mutter-3.26.2.orig/src/wayland/meta-wayland-versions.h	2017-10-05 19:06:58.000000000 +0200
+++ ./mutter-3.26.2/src/wayland/meta-wayland-versions.h	2017-12-08 18:57:47.596610926 +0100
@@ -49,5 +49,6 @@
 #define META_ZXDG_IMPORTER_V1_VERSION       1
 #define META_ZWP_LINUX_DMABUF_V1_VERSION    3
 #define META_ZWP_KEYBOARD_SHORTCUTS_INHIBIT_V1_VERSION 1
+#define META_WP_VIEWPORTER_VERSION          1
 
 #endif
--- ./mutter-3.26.2.orig/src/wayland/protocol/viewporter.xml	1970-01-01 01:00:00.000000000 +0100
+++ ./mutter-3.26.2/src/wayland/protocol/viewporter.xml	2017-12-08 17:43:28.442967964 +0100
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="viewporter">
+
+  <copyright>
+    Copyright © 2013-2016 Collabora, Ltd.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice (including the next
+    paragraph) shall be included in all copies or substantial portions of the
+    Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+  </copyright>
+
+  <interface name="wp_viewporter" version="1">
+    <description summary="surface cropping and scaling">
+      The global interface exposing surface cropping and scaling
+      capabilities is used to instantiate an interface extension for a
+      wl_surface object. This extended interface will then allow
+      cropping and scaling the surface contents, effectively
+      disconnecting the direct relationship between the buffer and the
+      surface size.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="unbind from the cropping and scaling interface">
+	Informs the server that the client will not be using this
+	protocol object anymore. This does not affect any other objects,
+	wp_viewport objects included.
+      </description>
+    </request>
+
+    <enum name="error">
+      <entry name="viewport_exists" value="0"
+             summary="the surface already has a viewport object associated"/>
+    </enum>
+
+    <request name="get_viewport">
+      <description summary="extend surface interface for crop and scale">
+	Instantiate an interface extension for the given wl_surface to
+	crop and scale its content. If the given wl_surface already has
+	a wp_viewport object associated, the viewport_exists
+	protocol error is raised.
+      </description>
+      <arg name="id" type="new_id" interface="wp_viewport"
+           summary="the new viewport interface id"/>
+      <arg name="surface" type="object" interface="wl_surface"
+           summary="the surface"/>
+    </request>
+  </interface>
+
+  <interface name="wp_viewport" version="1">
+    <description summary="crop and scale interface to a wl_surface">
+      An additional interface to a wl_surface object, which allows the
+      client to specify the cropping and scaling of the surface
+      contents.
+
+      This interface works with two concepts: the source rectangle (src_x,
+      src_y, src_width, src_height), and the destination size (dst_width,
+      dst_height). The contents of the source rectangle are scaled to the
+      destination size, and content outside the source rectangle is ignored.
+      This state is double-buffered, and is applied on the next
+      wl_surface.commit.
+
+      The two parts of crop and scale state are independent: the source
+      rectangle, and the destination size. Initially both are unset, that
+      is, no scaling is applied. The whole of the current wl_buffer is
+      used as the source, and the surface size is as defined in
+      wl_surface.attach.
+
+      If the destination size is set, it causes the surface size to become
+      dst_width, dst_height. The source (rectangle) is scaled to exactly
+      this size. This overrides whatever the attached wl_buffer size is,
+      unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
+      has no content and therefore no size. Otherwise, the size is always
+      at least 1x1 in surface local coordinates.
+
+      If the source rectangle is set, it defines what area of the wl_buffer is
+      taken as the source. If the source rectangle is set and the destination
+      size is not set, then src_width and src_height must be integers, and the
+      surface size becomes the source rectangle size. This results in cropping
+      without scaling. If src_width or src_height are not integers and
+      destination size is not set, the bad_size protocol error is raised when
+      the surface state is applied.
+
+      The coordinate transformations from buffer pixel coordinates up to
+      the surface-local coordinates happen in the following order:
+        1. buffer_transform (wl_surface.set_buffer_transform)
+        2. buffer_scale (wl_surface.set_buffer_scale)
+        3. crop and scale (wp_viewport.set*)
+      This means, that the source rectangle coordinates of crop and scale
+      are given in the coordinates after the buffer transform and scale,
+      i.e. in the coordinates that would be the surface-local coordinates
+      if the crop and scale was not applied.
+
+      If src_x or src_y are negative, the bad_value protocol error is raised.
+      Otherwise, if the source rectangle is partially or completely outside of
+      the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
+      when the surface state is applied. A NULL wl_buffer does not raise the
+      out_of_buffer error.
+
+      The x, y arguments of wl_surface.attach are applied as normal to
+      the surface. They indicate how many pixels to remove from the
+      surface size from the left and the top. In other words, they are
+      still in the surface-local coordinate system, just like dst_width
+      and dst_height are.
+
+      If the wl_surface associated with the wp_viewport is destroyed,
+      all wp_viewport requests except 'destroy' raise the protocol error
+      no_surface.
+
+      If the wp_viewport object is destroyed, the crop and scale
+      state is removed from the wl_surface. The change will be applied
+      on the next wl_surface.commit.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="remove scaling and cropping from the surface">
+	The associated wl_surface's crop and scale state is removed.
+	The change is applied on the next wl_surface.commit.
+      </description>
+    </request>
+
+    <enum name="error">
+      <entry name="bad_value" value="0"
+	     summary="negative or zero values in width or height"/>
+      <entry name="bad_size" value="1"
+	     summary="destination size is not integer"/>
+      <entry name="out_of_buffer" value="2"
+	     summary="source rectangle extends outside of the content area"/>
+      <entry name="no_surface" value="3"
+	     summary="the wl_surface was destroyed"/>
+    </enum>
+
+    <request name="set_source">
+      <description summary="set the source rectangle for cropping">
+	Set the source rectangle of the associated wl_surface. See
+	wp_viewport for the description, and relation to the wl_buffer
+	size.
+
+	If all of x, y, width and height are -1.0, the source rectangle is
+	unset instead. Any other set of values where width or height are zero
+	or negative, or x or y are negative, raise the bad_value protocol
+	error.
+
+	The crop and scale state is double-buffered state, and will be
+	applied on the next wl_surface.commit.
+      </description>
+      <arg name="x" type="fixed" summary="source rectangle x"/>
+      <arg name="y" type="fixed" summary="source rectangle y"/>
+      <arg name="width" type="fixed" summary="source rectangle width"/>
+      <arg name="height" type="fixed" summary="source rectangle height"/>
+    </request>
+
+    <request name="set_destination">
+      <description summary="set the surface size for scaling">
+	Set the destination size of the associated wl_surface. See
+	wp_viewport for the description, and relation to the wl_buffer
+	size.
+
+	If width is -1 and height is -1, the destination size is unset
+	instead. Any other pair of values for width and height that
+	contains zero or negative values raises the bad_value protocol
+	error.
+
+	The crop and scale state is double-buffered state, and will be
+	applied on the next wl_surface.commit.
+      </description>
+      <arg name="width" type="int" summary="surface width"/>
+      <arg name="height" type="int" summary="surface height"/>
+    </request>
+  </interface>
+
+</protocol>
+
