diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h index 1a841de85..83eb964d4 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 5b2630b87..cc79d7d81 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; @@ -167,6 +173,16 @@ set_clip_region (MetaShapedTexture *self, priv->clip_region = cairo_region_copy (clip_region); } +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) { @@ -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; - return template; + 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 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; - return template; + if (priv->unblended_pipeline) + return priv->unblended_pipeline; + + 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); } @@ -747,6 +795,23 @@ meta_shaped_texture_set_texture (MetaShapedTexture *stex, set_cogl_texture (stex, texture); } +/** + * 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 02c3923dc..eeb2495bb 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 286c19abf..1ec2efbe9 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 e089ab72d..046806c36 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); } }