[mutter] wayland: Add support for EGL_WAYLAND_Y_INVERTED_WL



commit 41c96921d615a47353c0917f6dec2b1f8080e848
Author: Jonas Ådahl <jadahl gmail com>
Date:   Thu Oct 20 15:44:27 2016 +0800

    wayland: Add support for EGL_WAYLAND_Y_INVERTED_WL
    
    Add support for inverted Y Wayland buffers. OpenGL textures are by
    default inverted, so adding support for EGL_WAYLAND_Y_INVERTED_WL
    effectively means adding support for non-inverted, which makes the
    MetaShapedTexture apply a transformation when drawing only when querying
    EGL_WAYLAND_Y_INVERTED_WL resulted in the response "EGL_FALSE".
    
    https://bugzilla.gnome.org/show_bug.cgi?id=773629

 src/compositor/meta-shaped-texture-private.h |    2 +
 src/compositor/meta-shaped-texture.c         |  139 +++++++++++++++++++-------
 src/wayland/meta-wayland-buffer.c            |   15 +++-
 src/wayland/meta-wayland-buffer.h            |    2 +
 src/wayland/meta-wayland-surface.c           |   13 ++-
 5 files changed, 128 insertions(+), 43 deletions(-)
---
diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h
index 1a841de..83eb964 100644
--- a/src/compositor/meta-shaped-texture-private.h
+++ b/src/compositor/meta-shaped-texture-private.h
@@ -32,6 +32,8 @@
 ClutterActor *meta_shaped_texture_new (void);
 void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
                                       CoglTexture       *texture);
+void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
+                                            gboolean           is_y_inverted);
 void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
                                             guint              fallback_width,
                                             guint              fallback_height);
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 5b2630b..cc79d7d 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -78,6 +78,12 @@ struct _MetaShapedTexturePrivate
   CoglTexture *texture;
   CoglTexture *mask_texture;
 
+  CoglPipeline *base_pipeline;
+  CoglPipeline *masked_pipeline;
+  CoglPipeline *unblended_pipeline;
+
+  gboolean is_y_inverted;
+
   /* The region containing only fully opaque pixels */
   cairo_region_t *opaque_region;
 
@@ -168,6 +174,16 @@ set_clip_region (MetaShapedTexture *self,
 }
 
 static void
+meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
+{
+  MetaShapedTexturePrivate *priv = stex->priv;
+
+  g_clear_pointer (&priv->base_pipeline, cogl_object_unref);
+  g_clear_pointer (&priv->masked_pipeline, cogl_object_unref);
+  g_clear_pointer (&priv->unblended_pipeline, cogl_object_unref);
+}
+
+static void
 meta_shaped_texture_dispose (GObject *object)
 {
   MetaShapedTexture *self = (MetaShapedTexture *) object;
@@ -184,61 +200,93 @@ meta_shaped_texture_dispose (GObject *object)
   set_unobscured_region (self, NULL);
   set_clip_region (self, NULL);
 
+  meta_shaped_texture_reset_pipelines (self);
+
   G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
 }
 
 static CoglPipeline *
-get_base_pipeline (CoglContext *ctx)
+get_base_pipeline (MetaShapedTexture *stex,
+                   CoglContext       *ctx)
 {
-  static CoglPipeline *template = NULL;
-  if (G_UNLIKELY (template == NULL))
+  MetaShapedTexturePrivate *priv = stex->priv;
+  CoglPipeline *pipeline;
+
+  if (priv->base_pipeline)
+    return priv->base_pipeline;
+
+  pipeline = cogl_pipeline_new (ctx);
+  cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0,
+                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+  cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0,
+                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+  cogl_pipeline_set_layer_wrap_mode_s (pipeline, 1,
+                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+  cogl_pipeline_set_layer_wrap_mode_t (pipeline, 1,
+                                       COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+  if (!priv->is_y_inverted)
     {
-      template = cogl_pipeline_new (ctx);
-      cogl_pipeline_set_layer_wrap_mode_s (template, 0, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
-      cogl_pipeline_set_layer_wrap_mode_t (template, 0, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
-      cogl_pipeline_set_layer_wrap_mode_s (template, 1, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
-      cogl_pipeline_set_layer_wrap_mode_t (template, 1, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
+      CoglMatrix matrix;
+
+      cogl_matrix_init_identity (&matrix);
+      cogl_matrix_scale (&matrix, 1, -1, 1);
+      cogl_matrix_translate (&matrix, 0, -1, 0);
+      cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
     }
-  return template;
+
+  priv->base_pipeline = pipeline;
+
+  return priv->base_pipeline;
 }
 
 static CoglPipeline *
-get_unmasked_pipeline (CoglContext *ctx)
+get_unmasked_pipeline (MetaShapedTexture *stex,
+                       CoglContext       *ctx)
 {
-  return get_base_pipeline (ctx);
+  return get_base_pipeline (stex, ctx);
 }
 
 static CoglPipeline *
-get_masked_pipeline (CoglContext *ctx)
+get_masked_pipeline (MetaShapedTexture *stex,
+                     CoglContext       *ctx)
 {
-  static CoglPipeline *template = NULL;
-  if (G_UNLIKELY (template == NULL))
-    {
-      template = cogl_pipeline_copy (get_base_pipeline (ctx));
-      cogl_pipeline_set_layer_combine (template, 1,
-                                       "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
-                                       NULL);
-    }
+  MetaShapedTexturePrivate *priv = stex->priv;
+  CoglPipeline *pipeline;
+
+  if (priv->masked_pipeline)
+    return priv->masked_pipeline;
+
+  pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
+  cogl_pipeline_set_layer_combine (pipeline, 1,
+                                   "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
+                                   NULL);
+
+  priv->masked_pipeline = pipeline;
 
-  return template;
+  return pipeline;
 }
 
 static CoglPipeline *
-get_unblended_pipeline (CoglContext *ctx)
+get_unblended_pipeline (MetaShapedTexture *stex,
+                        CoglContext       *ctx)
 {
-  static CoglPipeline *template = NULL;
-  if (G_UNLIKELY (template == NULL))
-    {
-      CoglColor color;
-      template = cogl_pipeline_copy (get_base_pipeline (ctx));
-      cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
-      cogl_pipeline_set_blend (template,
-                               "RGBA = ADD (SRC_COLOR, 0)",
-                               NULL);
-      cogl_pipeline_set_color (template, &color);
-    }
+  MetaShapedTexturePrivate *priv = stex->priv;
+  CoglPipeline *pipeline;
+  CoglColor color;
+
+  if (priv->unblended_pipeline)
+    return priv->unblended_pipeline;
 
-  return template;
+  pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
+  cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
+  cogl_pipeline_set_blend (pipeline,
+                           "RGBA = ADD (SRC_COLOR, 0)",
+                           NULL);
+  cogl_pipeline_set_color (pipeline, &color);
+
+  priv->unblended_pipeline = pipeline;
+
+  return pipeline;
 }
 
 static void
@@ -439,7 +487,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
 
       if (!cairo_region_is_empty (region))
         {
-          opaque_pipeline = get_unblended_pipeline (ctx);
+          opaque_pipeline = get_unblended_pipeline (stex, ctx);
           cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
           cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
 
@@ -471,11 +519,11 @@ meta_shaped_texture_paint (ClutterActor *actor)
 
       if (priv->mask_texture == NULL)
         {
-          blended_pipeline = get_unmasked_pipeline (ctx);
+          blended_pipeline = get_unmasked_pipeline (stex, ctx);
         }
       else
         {
-          blended_pipeline = get_masked_pipeline (ctx);
+          blended_pipeline = get_masked_pipeline (stex, ctx);
           cogl_pipeline_set_layer_texture (blended_pipeline, 1, priv->mask_texture);
           cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
         }
@@ -748,6 +796,23 @@ meta_shaped_texture_set_texture (MetaShapedTexture *stex,
 }
 
 /**
+ * meta_shaped_texture_set_is_y_inverted: (skip)
+ */
+void
+meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
+                                       gboolean           is_y_inverted)
+{
+  MetaShapedTexturePrivate *priv = stex->priv;
+
+  if (priv->is_y_inverted == is_y_inverted)
+    return;
+
+  meta_shaped_texture_reset_pipelines (stex);
+
+  priv->is_y_inverted = is_y_inverted;
+}
+
+/**
  * meta_shaped_texture_get_texture:
  * @stex: The #MetaShapedTexture
  *
diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c
index 02c3923..eeb2495 100644
--- a/src/wayland/meta-wayland-buffer.c
+++ b/src/wayland/meta-wayland-buffer.c
@@ -191,6 +191,7 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
   wl_shm_buffer_end_access (shm_buffer);
 
   buffer->texture = texture;
+  buffer->is_y_inverted = TRUE;
 
   if (!buffer->texture)
     return FALSE;
@@ -208,7 +209,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
   CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
   EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
   EGLContext egl_context = cogl_egl_context_get_egl_context (cogl_context);
-  int format, width, height;
+  int format, width, height, y_inverted;
   CoglPixelFormat cogl_format;
   EGLImageKHR egl_image;
   CoglTexture2D *texture;
@@ -231,6 +232,11 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
                                       error))
     return FALSE;
 
+  if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
+                                      EGL_WAYLAND_Y_INVERTED_WL, &y_inverted,
+                                      NULL))
+    y_inverted = EGL_TRUE;
+
   switch (format)
     {
     case EGL_TEXTURE_RGB:
@@ -265,6 +271,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
     return FALSE;
 
   buffer->texture = COGL_TEXTURE (texture);
+  buffer->is_y_inverted = !!y_inverted;
 
   return TRUE;
 }
@@ -301,6 +308,12 @@ meta_wayland_buffer_get_texture (MetaWaylandBuffer *buffer)
   return buffer->texture;
 }
 
+gboolean
+meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer)
+{
+  return buffer->is_y_inverted;
+}
+
 static gboolean
 process_shm_buffer_damage (MetaWaylandBuffer *buffer,
                            cairo_region_t    *region,
diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h
index 286c19a..1ec2efb 100644
--- a/src/wayland/meta-wayland-buffer.h
+++ b/src/wayland/meta-wayland-buffer.h
@@ -39,6 +39,7 @@ struct _MetaWaylandBuffer
   struct wl_listener destroy_listener;
 
   CoglTexture *texture;
+  gboolean is_y_inverted;
 };
 
 #define META_TYPE_WAYLAND_BUFFER (meta_wayland_buffer_get_type ())
@@ -49,6 +50,7 @@ MetaWaylandBuffer *     meta_wayland_buffer_from_resource       (struct wl_resou
 gboolean                meta_wayland_buffer_attach              (MetaWaylandBuffer     *buffer,
                                                                  GError               **error);
 CoglTexture *           meta_wayland_buffer_get_texture         (MetaWaylandBuffer     *buffer);
+gboolean                meta_wayland_buffer_is_y_inverted       (MetaWaylandBuffer     *buffer);
 void                    meta_wayland_buffer_process_damage      (MetaWaylandBuffer     *buffer,
                                                                  cairo_region_t        *region);
 
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index e089ab7..046806c 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -51,6 +51,7 @@
 #include "meta-window-wayland.h"
 
 #include "compositor/region-utils.h"
+#include "compositor/meta-shaped-texture-private.h"
 
 #include "meta-surface-actor.h"
 #include "meta-surface-actor-wayland.h"
@@ -701,9 +702,6 @@ static void
 apply_pending_state (MetaWaylandSurface      *surface,
                      MetaWaylandPendingState *pending)
 {
-  MetaSurfaceActorWayland *surface_actor_wayland =
-    META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
-
   if (surface->role)
     {
       meta_wayland_surface_role_pre_commit (surface->role, pending);
@@ -755,11 +753,16 @@ apply_pending_state (MetaWaylandSurface      *surface,
 
           if (switched_buffer)
             {
+              MetaShapedTexture *stex;
               CoglTexture *texture;
+              gboolean is_y_inverted;
 
+              stex = meta_surface_actor_get_texture (surface->surface_actor);
               texture = meta_wayland_buffer_get_texture (pending->buffer);
-              meta_surface_actor_wayland_set_texture (surface_actor_wayland,
-                                                      texture);
+              is_y_inverted = meta_wayland_buffer_is_y_inverted (pending->buffer);
+
+              meta_shaped_texture_set_texture (stex, texture);
+              meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted);
             }
         }
 


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