Compare commits
	
		
			2 Commits
		
	
	
		
			wip/fmuell
			...
			wip/viewpo
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					0829749049 | ||
| 
						 | 
					725d0ad680 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -66,6 +66,8 @@ src/meta-dbus-idle-monitor.[ch]
 | 
			
		||||
src/meta-dbus-login1.[ch]
 | 
			
		||||
src/gtk-shell-protocol.c
 | 
			
		||||
src/gtk-shell-server-protocol.h
 | 
			
		||||
src/scaler-protocol.c
 | 
			
		||||
src/scaler-server-protocol.h
 | 
			
		||||
src/xdg-shell-protocol.c
 | 
			
		||||
src/xdg-shell-server-protocol.h
 | 
			
		||||
src/xserver-protocol.c
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,8 @@ mutter_built_sources += \
 | 
			
		||||
	gtk-shell-server-protocol.h		\
 | 
			
		||||
	xdg-shell-protocol.c			\
 | 
			
		||||
	xdg-shell-server-protocol.h		\
 | 
			
		||||
	scaler-protocol.c			\
 | 
			
		||||
	scaler-server-protocol.h		\
 | 
			
		||||
	$(NULL)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,4 +34,9 @@ void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
 | 
			
		||||
                                      CoglTexture       *texture);
 | 
			
		||||
gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
 | 
			
		||||
 | 
			
		||||
void meta_shaped_texture_set_viewport (MetaShapedTexture     *stex,
 | 
			
		||||
                                       cairo_rectangle_int_t *src_rect,
 | 
			
		||||
                                       int                    dest_width,
 | 
			
		||||
                                       int                    dest_height);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -85,7 +85,12 @@ struct _MetaShapedTexturePrivate
 | 
			
		||||
  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 dest_width, dest_height;
 | 
			
		||||
 | 
			
		||||
  guint create_mipmaps : 1;
 | 
			
		||||
};
 | 
			
		||||
@@ -136,7 +141,7 @@ set_unobscured_region (MetaShapedTexture *self,
 | 
			
		||||
  g_clear_pointer (&priv->unobscured_region, (GDestroyNotify) cairo_region_destroy);
 | 
			
		||||
  if (unobscured_region)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_rectangle_int_t bounds = { 0, 0, priv->tex_width, priv->tex_height };
 | 
			
		||||
      cairo_rectangle_int_t bounds = { 0, 0, priv->dest_width, priv->dest_height };
 | 
			
		||||
      priv->unobscured_region = cairo_region_copy (unobscured_region);
 | 
			
		||||
      cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
 | 
			
		||||
    }
 | 
			
		||||
@@ -212,24 +217,45 @@ get_unblended_pipeline (CoglContext *ctx)
 | 
			
		||||
  return cogl_pipeline_copy (template);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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];
 | 
			
		||||
@@ -241,6 +267,32 @@ paint_clipped_rectangle (CoglFramebuffer       *fb,
 | 
			
		||||
                                                 &coords[0], 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
@@ -274,8 +326,7 @@ set_cogl_texture (MetaShapedTexture *stex,
 | 
			
		||||
    {
 | 
			
		||||
      priv->tex_width = width;
 | 
			
		||||
      priv->tex_height = height;
 | 
			
		||||
      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
 | 
			
		||||
@@ -292,7 +343,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexture *stex = (MetaShapedTexture *) actor;
 | 
			
		||||
  MetaShapedTexturePrivate *priv = stex->priv;
 | 
			
		||||
  guint tex_width, tex_height;
 | 
			
		||||
  guint dest_width, dest_height;
 | 
			
		||||
  guchar opacity;
 | 
			
		||||
  CoglContext *ctx;
 | 
			
		||||
  CoglFramebuffer *fb;
 | 
			
		||||
@@ -329,13 +380,13 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
  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.
 | 
			
		||||
@@ -418,7 +469,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
            {
 | 
			
		||||
              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);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          cogl_object_unref (opaque_pipeline);
 | 
			
		||||
@@ -473,16 +524,13 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
              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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      cogl_object_unref (blended_pipeline);
 | 
			
		||||
@@ -505,10 +553,10 @@ meta_shaped_texture_get_preferred_width (ClutterActor *self,
 | 
			
		||||
  priv = META_SHAPED_TEXTURE (self)->priv;
 | 
			
		||||
 | 
			
		||||
  if (min_width_p)
 | 
			
		||||
    *min_width_p = priv->tex_width;
 | 
			
		||||
    *min_width_p = priv->dest_width;
 | 
			
		||||
 | 
			
		||||
  if (natural_width_p)
 | 
			
		||||
    *natural_width_p = priv->tex_width;
 | 
			
		||||
    *natural_width_p = priv->dest_width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -524,10 +572,10 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self,
 | 
			
		||||
  priv = META_SHAPED_TEXTURE (self)->priv;
 | 
			
		||||
 | 
			
		||||
  if (min_height_p)
 | 
			
		||||
    *min_height_p = priv->tex_height;
 | 
			
		||||
    *min_height_p = priv->dest_height;
 | 
			
		||||
 | 
			
		||||
  if (natural_height_p)
 | 
			
		||||
    *natural_height_p = priv->tex_height;
 | 
			
		||||
    *natural_height_p = priv->dest_height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static cairo_region_t *
 | 
			
		||||
@@ -762,6 +810,22 @@ meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
 | 
			
		||||
    priv->opaque_region = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 
 | 
			
		||||
@@ -235,6 +235,16 @@ meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
 | 
			
		||||
  meta_shaped_texture_set_opaque_region (priv->texture, region);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,11 @@ void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
 | 
			
		||||
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
 | 
			
		||||
                                           cairo_region_t   *region);
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@
 | 
			
		||||
#include <wayland-server.h>
 | 
			
		||||
#include "gtk-shell-server-protocol.h"
 | 
			
		||||
#include "xdg-shell-server-protocol.h"
 | 
			
		||||
#include "scaler-server-protocol.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
#include "meta-xwayland-private.h"
 | 
			
		||||
@@ -265,6 +266,7 @@ pending_state_init (MetaWaylandPendingState *state)
 | 
			
		||||
  wl_list_init (&state->frame_callback_list);
 | 
			
		||||
 | 
			
		||||
  state->has_new_geometry = FALSE;
 | 
			
		||||
  state->viewport.changed = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -420,6 +422,12 @@ commit_pending_state (MetaWaylandSurface      *surface,
 | 
			
		||||
  wl_list_insert_list (&compositor->frame_callbacks, &pending->frame_callback_list);
 | 
			
		||||
  wl_list_init (&pending->frame_callback_list);
 | 
			
		||||
 | 
			
		||||
  if (pending->viewport.changed)
 | 
			
		||||
    meta_surface_actor_set_viewport (surface->surface_actor,
 | 
			
		||||
                                     &pending->viewport.src_rect,
 | 
			
		||||
                                     pending->viewport.dest_width,
 | 
			
		||||
                                     pending->viewport.dest_height);
 | 
			
		||||
 | 
			
		||||
  if (surface == compositor->seat->pointer.cursor_surface)
 | 
			
		||||
    cursor_surface_commit (surface, pending);
 | 
			
		||||
  else if (meta_wayland_data_device_is_dnd_surface (&compositor->seat->data_device, surface))
 | 
			
		||||
@@ -1681,6 +1689,136 @@ bind_subcompositor (struct wl_client *client,
 | 
			
		||||
  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
 | 
			
		||||
wl_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
 | 
			
		||||
wl_viewport_set (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,
 | 
			
		||||
                 int dst_width,
 | 
			
		||||
                 int dst_height)
 | 
			
		||||
{
 | 
			
		||||
  viewport_set_src (resource, src_x, src_y, src_width, src_height);
 | 
			
		||||
  viewport_set_dest (resource, dst_width, dst_height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
wl_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
 | 
			
		||||
wl_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 wl_viewport_interface meta_wayland_viewport_interface = {
 | 
			
		||||
  wl_viewport_destroy,
 | 
			
		||||
  wl_viewport_set,
 | 
			
		||||
  wl_viewport_set_source,
 | 
			
		||||
  wl_viewport_set_destination,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
wl_scaler_destroy (struct wl_client *client,
 | 
			
		||||
                   struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
  wl_resource_destroy (resource);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
wl_scaler_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,
 | 
			
		||||
                              WL_SCALER_ERROR_VIEWPORT_EXISTS,
 | 
			
		||||
                              "viewport already exists on surface");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  resource = wl_resource_create (client, &wl_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 wl_scaler_interface meta_wayland_scaler_interface = {
 | 
			
		||||
  wl_scaler_destroy,
 | 
			
		||||
  wl_scaler_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, &wl_scaler_interface, version, id);
 | 
			
		||||
  wl_resource_set_implementation (resource, &meta_wayland_scaler_interface, data, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_shell_init (MetaWaylandCompositor *compositor)
 | 
			
		||||
{
 | 
			
		||||
@@ -1707,6 +1845,12 @@ meta_wayland_shell_init (MetaWaylandCompositor *compositor)
 | 
			
		||||
                        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,
 | 
			
		||||
                        &wl_scaler_interface,
 | 
			
		||||
                        META_WL_SCALER_VERSION,
 | 
			
		||||
                        compositor, bind_scaler) == NULL)
 | 
			
		||||
    g_error ("Failed to register a global wl-subcompositor object");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,12 @@ typedef struct
 | 
			
		||||
 | 
			
		||||
  MetaRectangle new_geometry;
 | 
			
		||||
  gboolean has_new_geometry;
 | 
			
		||||
 | 
			
		||||
  struct {
 | 
			
		||||
    gboolean changed;
 | 
			
		||||
    cairo_rectangle_int_t src_rect;
 | 
			
		||||
    int32_t dest_width, dest_height;
 | 
			
		||||
  } viewport;
 | 
			
		||||
} MetaWaylandPendingState;
 | 
			
		||||
 | 
			
		||||
struct _MetaWaylandSurface
 | 
			
		||||
@@ -72,6 +78,7 @@ struct _MetaWaylandSurface
 | 
			
		||||
  int scale;
 | 
			
		||||
  int32_t offset_x, offset_y;
 | 
			
		||||
  GList *subsurfaces;
 | 
			
		||||
  gboolean has_viewport;
 | 
			
		||||
 | 
			
		||||
  /* All the pending state that wl_surface.commit will apply. */
 | 
			
		||||
  MetaWaylandPendingState pending;
 | 
			
		||||
 
 | 
			
		||||
@@ -44,5 +44,6 @@
 | 
			
		||||
#define META_XSERVER_VERSION                1
 | 
			
		||||
#define META_GTK_SHELL_VERSION              1
 | 
			
		||||
#define META_WL_SUBCOMPOSITOR_VERSION       1
 | 
			
		||||
#define META_WL_SCALER_VERSION              2
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										210
									
								
								src/wayland/protocol/scaler.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								src/wayland/protocol/scaler.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<protocol name="scaler">
 | 
			
		||||
 | 
			
		||||
  <copyright>
 | 
			
		||||
    Copyright © 2013-2014 Collabora, Ltd.
 | 
			
		||||
 | 
			
		||||
    Permission to use, copy, modify, distribute, and sell this
 | 
			
		||||
    software and its documentation for any purpose is hereby granted
 | 
			
		||||
    without fee, provided that the above copyright notice appear in
 | 
			
		||||
    all copies and that both that copyright notice and this permission
 | 
			
		||||
    notice appear in supporting documentation, and that the name of
 | 
			
		||||
    the copyright holders not be used in advertising or publicity
 | 
			
		||||
    pertaining to distribution of the software without specific,
 | 
			
		||||
    written prior permission.  The copyright holders make no
 | 
			
		||||
    representations about the suitability of this software for any
 | 
			
		||||
    purpose.  It is provided "as is" without express or implied
 | 
			
		||||
    warranty.
 | 
			
		||||
 | 
			
		||||
    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 | 
			
		||||
    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 | 
			
		||||
    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 | 
			
		||||
    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | 
			
		||||
    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 | 
			
		||||
    THIS SOFTWARE.
 | 
			
		||||
  </copyright>
 | 
			
		||||
 | 
			
		||||
  <interface name="wl_scaler" version="2">
 | 
			
		||||
    <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,
 | 
			
		||||
	wl_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 wl_viewport object associated, the viewport_exists
 | 
			
		||||
	protocol error is raised.
 | 
			
		||||
      </description>
 | 
			
		||||
 | 
			
		||||
      <arg name="id" type="new_id" interface="wl_viewport"
 | 
			
		||||
           summary="the new viewport interface id"/>
 | 
			
		||||
      <arg name="surface" type="object" interface="wl_surface"
 | 
			
		||||
           summary="the surface"/>
 | 
			
		||||
    </request>
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
  <interface name="wl_viewport" version="2">
 | 
			
		||||
    <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 allows to define the source rectangle (src_x,
 | 
			
		||||
      src_y, src_width, src_height) from where to take the wl_buffer
 | 
			
		||||
      contents, and scale that to destination size (dst_width,
 | 
			
		||||
      dst_height). 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 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, the surface size becomes the source
 | 
			
		||||
      rectangle size rounded up to the nearest integer. If the source size
 | 
			
		||||
      is already exactly integers, this results in cropping without scaling.
 | 
			
		||||
 | 
			
		||||
      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 (wl_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 the source rectangle is partially or completely outside of the
 | 
			
		||||
      wl_buffer, then the surface contents are undefined (not void), and
 | 
			
		||||
      the surface size is still dst_width, dst_height.
 | 
			
		||||
 | 
			
		||||
      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 wl_viewport is destroyed,
 | 
			
		||||
      the wl_viewport object becomes inert.
 | 
			
		||||
 | 
			
		||||
      If the wl_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"/>
 | 
			
		||||
    </enum>
 | 
			
		||||
 | 
			
		||||
    <request name="set">
 | 
			
		||||
      <description summary="set the crop and scale state">
 | 
			
		||||
	Set both source rectangle and destination size of the associated
 | 
			
		||||
	wl_surface. See wl_viewport for the description, and relation to
 | 
			
		||||
	the wl_buffer size.
 | 
			
		||||
 | 
			
		||||
	The bad_value protocol error is raised if src_width or
 | 
			
		||||
	src_height is negative, or if dst_width or dst_height is not
 | 
			
		||||
	positive.
 | 
			
		||||
 | 
			
		||||
	The crop and scale state is double-buffered state, and will be
 | 
			
		||||
	applied on the next wl_surface.commit.
 | 
			
		||||
 | 
			
		||||
	Arguments dst_x and dst_y do not exist here, use the x and y
 | 
			
		||||
	arguments to wl_surface.attach. The x, y, dst_width, and dst_height
 | 
			
		||||
	define the surface-local coordinate system irrespective of the
 | 
			
		||||
	attached wl_buffer size.
 | 
			
		||||
      </description>
 | 
			
		||||
 | 
			
		||||
      <arg name="src_x" type="fixed" summary="source rectangle x"/>
 | 
			
		||||
      <arg name="src_y" type="fixed" summary="source rectangle y"/>
 | 
			
		||||
      <arg name="src_width" type="fixed" summary="source rectangle width"/>
 | 
			
		||||
      <arg name="src_height" type="fixed" summary="source rectangle height"/>
 | 
			
		||||
      <arg name="dst_width" type="int" summary="surface width"/>
 | 
			
		||||
      <arg name="dst_height" type="int" summary="surface height"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <request name="set_source" since="2">
 | 
			
		||||
      <description summary="set the source rectangle for cropping">
 | 
			
		||||
	Set the source rectangle of the associated wl_surface. See
 | 
			
		||||
	wl_viewport for the description, and relation to the wl_buffer
 | 
			
		||||
	size.
 | 
			
		||||
 | 
			
		||||
	If width is -1.0 and height is -1.0, 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="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" since="2">
 | 
			
		||||
      <description summary="set the surface size for scaling">
 | 
			
		||||
	Set the destination size of the associated wl_surface. See
 | 
			
		||||
	wl_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.
 | 
			
		||||
 | 
			
		||||
	Arguments x and y do not exist here, use the x and y arguments to
 | 
			
		||||
	wl_surface.attach. The x, y, width, and height define the
 | 
			
		||||
	surface-local coordinate system irrespective of the attached
 | 
			
		||||
	wl_buffer size.
 | 
			
		||||
      </description>
 | 
			
		||||
 | 
			
		||||
      <arg name="width" type="int" summary="surface width"/>
 | 
			
		||||
      <arg name="height" type="int" summary="surface height"/>
 | 
			
		||||
    </request>
 | 
			
		||||
  </interface>
 | 
			
		||||
</protocol>
 | 
			
		||||
		Reference in New Issue
	
	Block a user