diff options
author | Niels De Graef <niels.degraef@barco.com> | 2019-06-19 08:21:33 +0200 |
---|---|---|
committer | Niels De Graef <niels.degraef@barco.com> | 2019-06-24 15:14:01 +0200 |
commit | 784b1750c42eea17901bf5d2a9707f8989841cf8 (patch) | |
tree | 18e1caccd73c78271ba29b7203c207870aae0438 | |
parent | f8747a2fe248ff44355177ef27f90f2b55ef0514 (diff) | |
download | mutter-784b1750c42eea17901bf5d2a9707f8989841cf8.tar.gz |
wayland: Support complex (YUV) pixel formats
In the previous commits, we added the possibility to use pixel formats
which are complex (YUV-based and/or multi-planar) inside Cogl. Use this
new feature by assuming we get a CoglMultiPlaneTexture, rather than a
"simple" CoglTexture.
To easily test whether this works, one can use GStreamer pipelines
(you'll need gst-plugins-bad for this to work):
For normal BGRA (this should already work before this commit):
```
$ gst-launch-1.0 videotestsrc ! "video/x-raw" ! waylandsink
```
For NV12 (a popular video format):
```
$ gst-launch-1.0 videotestsrc ! "video/x-raw,format=NV12" ! waylandsink
```
For YUV 4:2:2 (another video format):
```
$ gst-launch-1.0 videotestsrc ! "video/x-raw,format=Y42B" ! waylandsink
```
You can also replace with other video sinks, like `vaapisink`.
`glimagesink` also works, but for some reason seems to unconditionally
convert to RGBA before submitting a texture (so it doesn't do a lot
really).
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=705514
-rw-r--r-- | src/compositor/meta-shaped-texture-private.h | 2 | ||||
-rw-r--r-- | src/compositor/meta-shaped-texture.c | 172 | ||||
-rw-r--r-- | src/compositor/meta-surface-actor-x11.c | 11 | ||||
-rw-r--r-- | src/compositor/meta-surface-actor.c | 10 | ||||
-rw-r--r-- | src/compositor/meta-texture-tower.c | 158 | ||||
-rw-r--r-- | src/compositor/meta-texture-tower.h | 6 | ||||
-rw-r--r-- | src/compositor/meta-window-actor.c | 7 | ||||
-rw-r--r-- | src/meta/meta-shaped-texture.h | 2 | ||||
-rw-r--r-- | src/wayland/meta-wayland-buffer.c | 363 | ||||
-rw-r--r-- | src/wayland/meta-wayland-buffer.h | 16 | ||||
-rw-r--r-- | src/wayland/meta-wayland-cursor-surface.c | 9 | ||||
-rw-r--r-- | src/wayland/meta-wayland-dma-buf.c | 218 | ||||
-rw-r--r-- | src/wayland/meta-wayland-dma-buf.h | 8 | ||||
-rw-r--r-- | src/wayland/meta-wayland-egl-stream.c | 21 | ||||
-rw-r--r-- | src/wayland/meta-wayland-egl-stream.h | 4 | ||||
-rw-r--r-- | src/wayland/meta-wayland-shell-surface.c | 6 | ||||
-rw-r--r-- | src/wayland/meta-wayland-surface.c | 8 | ||||
-rw-r--r-- | src/wayland/meta-wayland-surface.h | 4 | ||||
-rw-r--r-- | src/wayland/meta-wayland.c | 22 |
19 files changed, 699 insertions, 348 deletions
diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h index a86a2bff0..43be08127 100644 --- a/src/compositor/meta-shaped-texture-private.h +++ b/src/compositor/meta-shaped-texture-private.h @@ -32,7 +32,7 @@ ClutterActor *meta_shaped_texture_new (void); void meta_shaped_texture_set_texture (MetaShapedTexture *stex, - CoglTexture *texture); + CoglMultiPlaneTexture *texture); void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex, gboolean is_y_inverted); void meta_shaped_texture_set_snippet (MetaShapedTexture *stex, diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index 90a02210d..df64d1d6a 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -89,7 +89,7 @@ struct _MetaShapedTexture MetaTextureTower *paint_tower; - CoglTexture *texture; + CoglMultiPlaneTexture *texture; CoglTexture *mask_texture; CoglSnippet *snippet; @@ -97,6 +97,8 @@ struct _MetaShapedTexture CoglPipeline *masked_pipeline; CoglPipeline *unblended_pipeline; + CoglPixelFormatConversion *pixel_format_conversion; + gboolean is_y_inverted; /* The region containing only fully opaque pixels */ @@ -277,9 +279,11 @@ set_clip_region (MetaShapedTexture *stex, static void meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex) { - g_clear_pointer (&stex->base_pipeline, cogl_object_unref); - g_clear_pointer (&stex->masked_pipeline, cogl_object_unref); - g_clear_pointer (&stex->unblended_pipeline, cogl_object_unref); + cogl_clear_object (&stex->pixel_format_conversion); + + cogl_clear_object (&stex->base_pipeline); + cogl_clear_object (&stex->masked_pipeline); + cogl_clear_object (&stex->unblended_pipeline); } static void @@ -297,7 +301,7 @@ meta_shaped_texture_dispose (GObject *object) meta_texture_tower_free (stex->paint_tower); stex->paint_tower = NULL; - g_clear_pointer (&stex->texture, cogl_object_unref); + cogl_clear_object (&stex->texture); g_clear_pointer (&stex->opaque_region, cairo_region_destroy); meta_shaped_texture_set_mask_texture (stex, NULL); @@ -306,7 +310,7 @@ meta_shaped_texture_dispose (GObject *object) meta_shaped_texture_reset_pipelines (stex); - g_clear_pointer (&stex->snippet, cogl_object_unref); + cogl_clear_object (&stex->snippet); G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object); } @@ -317,19 +321,23 @@ get_base_pipeline (MetaShapedTexture *stex, { CoglPipeline *pipeline; CoglMatrix matrix; + CoglPixelFormat format; + uint8_t i, n_planes; if (stex->base_pipeline) return stex->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); + + format = cogl_multi_plane_texture_get_format (stex->texture); + n_planes = cogl_multi_plane_texture_get_n_planes (stex->texture); + for (i = 0; i < n_planes; i++) + { + cogl_pipeline_set_layer_wrap_mode_s (pipeline, i, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); + cogl_pipeline_set_layer_wrap_mode_t (pipeline, i, + COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); + } cogl_matrix_init_identity (&matrix); @@ -409,11 +417,24 @@ get_base_pipeline (MetaShapedTexture *stex, 0); } - cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); - cogl_pipeline_set_layer_matrix (pipeline, 1, &matrix); + for (i = 0; i < n_planes + 1; i++) + cogl_pipeline_set_layer_matrix (pipeline, i, &matrix); + + cogl_clear_object (&stex->pixel_format_conversion); + stex->pixel_format_conversion = cogl_pixel_format_conversion_new (format); + + if (stex->pixel_format_conversion) + { + cogl_pixel_format_conversion_attach_to_pipeline (stex->pixel_format_conversion, + pipeline, + n_planes - 1); + } if (stex->snippet) - cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet); + { + for (i = 0; i < n_planes; i++) + cogl_pipeline_add_layer_snippet (pipeline, i, stex->snippet); + } stex->base_pipeline = pipeline; @@ -432,12 +453,14 @@ get_masked_pipeline (MetaShapedTexture *stex, CoglContext *ctx) { CoglPipeline *pipeline; + uint8_t n_planes; if (stex->masked_pipeline) return stex->masked_pipeline; pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx)); - cogl_pipeline_set_layer_combine (pipeline, 1, + n_planes = cogl_multi_plane_texture_get_n_planes (stex->texture); + cogl_pipeline_set_layer_combine (pipeline, n_planes, "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", NULL); @@ -451,17 +474,15 @@ get_unblended_pipeline (MetaShapedTexture *stex, CoglContext *ctx) { CoglPipeline *pipeline; - CoglColor color; if (stex->unblended_pipeline) return stex->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); + cogl_pipeline_set_color4ub (pipeline, 255, 255, 255, 255); stex->unblended_pipeline = pipeline; @@ -503,23 +524,21 @@ paint_clipped_rectangle (MetaShapedTexture *stex, } static void -set_cogl_texture (MetaShapedTexture *stex, - CoglTexture *cogl_tex) +set_planar_texture (MetaShapedTexture *stex, + CoglMultiPlaneTexture *planar_tex) { int width, height; g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); - if (stex->texture) - cogl_object_unref (stex->texture); + cogl_clear_object (&stex->texture); + stex->texture = planar_tex; - stex->texture = cogl_tex; - - if (cogl_tex != NULL) + if (planar_tex != NULL) { - cogl_object_ref (cogl_tex); - width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex)); - height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex)); + cogl_object_ref (planar_tex); + width = cogl_multi_plane_texture_get_width (planar_tex); + height = cogl_multi_plane_texture_get_height (planar_tex); } else { @@ -540,8 +559,11 @@ set_cogl_texture (MetaShapedTexture *stex, * previous buffer. We only queue a redraw in response to surface * damage. */ + /* if (FALSE) */ if (stex->create_mipmaps) - meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex); + { + meta_texture_tower_set_base_texture (stex->paint_tower, planar_tex); + } } static gboolean @@ -559,10 +581,10 @@ texture_is_idle_and_not_mipmapped (gpointer user_data) } static void -do_paint (MetaShapedTexture *stex, - CoglFramebuffer *fb, - CoglTexture *paint_tex, - cairo_region_t *clip_region) +do_paint (MetaShapedTexture *stex, + CoglFramebuffer *fb, + CoglMultiPlaneTexture *paint_tex, + cairo_region_t *clip_region) { double tex_scale; int dst_width, dst_height; @@ -575,8 +597,12 @@ do_paint (MetaShapedTexture *stex, CoglContext *ctx; ClutterActorBox alloc; CoglPipelineFilter filter; + uint8_t n_planes; clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL); + + n_planes = cogl_multi_plane_texture_get_n_planes (paint_tex); + ensure_size_valid (stex); dst_width = stex->dst_width; @@ -682,8 +708,15 @@ do_paint (MetaShapedTexture *stex, if (!cairo_region_is_empty (region)) { 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); + + for (i = 0; i < n_planes; i++) + { + CoglTexture *plane = cogl_multi_plane_texture_get_plane (paint_tex, i); + + + cogl_pipeline_set_layer_texture (opaque_pipeline, i, plane); + cogl_pipeline_set_layer_filters (opaque_pipeline, i, filter, filter); + } n_rects = cairo_region_num_rectangles (region); for (i = 0; i < n_rects; i++) @@ -714,6 +747,7 @@ do_paint (MetaShapedTexture *stex, if (!blended_tex_region || !cairo_region_is_empty (blended_tex_region)) { CoglPipeline *blended_pipeline; + guint i; if (stex->mask_texture == NULL) { @@ -722,16 +756,20 @@ do_paint (MetaShapedTexture *stex, else { blended_pipeline = get_masked_pipeline (stex, ctx); - cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture); - cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter); + cogl_pipeline_set_layer_texture (blended_pipeline, n_planes, stex->mask_texture); + cogl_pipeline_set_layer_filters (blended_pipeline, n_planes, filter, filter); } - cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex); - cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter); + for (i = 0; i < n_planes; i++) + { + CoglTexture *plane = cogl_multi_plane_texture_get_plane (paint_tex, i); - CoglColor color; - cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); - cogl_pipeline_set_color (blended_pipeline, &color); + cogl_pipeline_set_layer_texture (blended_pipeline, i, plane); + cogl_pipeline_set_layer_filters (blended_pipeline, i, filter, filter); + } + + cogl_pipeline_set_color4ub (blended_pipeline, + opacity, opacity, opacity, opacity); if (blended_tex_region) { @@ -773,7 +811,7 @@ static void meta_shaped_texture_paint (ClutterActor *actor) { MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor); - CoglTexture *paint_tex; + CoglMultiPlaneTexture *paint_tex; CoglFramebuffer *fb; if (!stex->texture) @@ -828,11 +866,11 @@ meta_shaped_texture_paint (ClutterActor *actor) } else { - paint_tex = COGL_TEXTURE (stex->texture); + paint_tex = stex->texture; } - if (cogl_texture_get_width (paint_tex) == 0 || - cogl_texture_get_height (paint_tex) == 0) + if (cogl_multi_plane_texture_get_width (paint_tex) == 0 || + cogl_multi_plane_texture_get_height (paint_tex) == 0) return; fb = cogl_get_draw_framebuffer (); @@ -906,7 +944,7 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, if (create_mipmaps != stex->create_mipmaps) { - CoglTexture *base_texture; + CoglMultiPlaneTexture *base_texture; stex->create_mipmaps = create_mipmaps; base_texture = create_mipmaps ? stex->texture : NULL; meta_texture_tower_set_base_texture (stex->paint_tower, base_texture); @@ -1089,15 +1127,15 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, /** * meta_shaped_texture_set_texture: * @stex: The #MetaShapedTexture - * @pixmap: The #CoglTexture to display + * @pixmap: The #CoglMultiPlaneTexture to display */ void meta_shaped_texture_set_texture (MetaShapedTexture *stex, - CoglTexture *texture) + CoglMultiPlaneTexture *texture) { g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); - set_cogl_texture (stex, texture); + set_planar_texture (stex, texture); } /** @@ -1127,7 +1165,7 @@ meta_shaped_texture_set_snippet (MetaShapedTexture *stex, meta_shaped_texture_reset_pipelines (stex); - g_clear_pointer (&stex->snippet, cogl_object_unref); + cogl_clear_object (&stex->snippet); if (snippet) stex->snippet = cogl_object_ref (snippet); } @@ -1138,11 +1176,12 @@ meta_shaped_texture_set_snippet (MetaShapedTexture *stex, * * Returns: (transfer none): the unshaped texture */ -CoglTexture * +CoglMultiPlaneTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex) { g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL); - return COGL_TEXTURE (stex->texture); + + return stex->texture; } /** @@ -1247,7 +1286,15 @@ meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex) static gboolean should_get_via_offscreen (MetaShapedTexture *stex) { - if (!cogl_texture_is_get_data_supported (stex->texture)) + CoglTexture *texture; + + /* If we have more than 1 plane, we can't access the data */ + if (cogl_multi_plane_texture_get_n_planes (stex->texture) > 1) + return TRUE; + + /* We have only 1 plane -> access it directly */ + texture = cogl_multi_plane_texture_get_plane (stex->texture, 0); + if (!cogl_texture_is_get_data_supported (texture)) return TRUE; if (stex->has_viewport_src_rect || stex->has_viewport_dst_size) @@ -1364,19 +1411,19 @@ get_image_via_offscreen (MetaShapedTexture *stex, * Returns: (transfer full): a new cairo surface to be freed with * cairo_surface_destroy(). */ + /* XXX Still need to fix this, but apparently only used for screenshot */ cairo_surface_t * meta_shaped_texture_get_image (MetaShapedTexture *stex, cairo_rectangle_int_t *clip) { cairo_rectangle_int_t *transformed_clip = NULL; - CoglTexture *texture, *mask_texture; + CoglTexture *texture; + CoglTexture *mask_texture; cairo_surface_t *surface; g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL); - texture = COGL_TEXTURE (stex->texture); - - if (texture == NULL) + if (stex->texture == NULL) return NULL; ensure_size_valid (stex); @@ -1409,6 +1456,9 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex, if (should_get_via_offscreen (stex)) return get_image_via_offscreen (stex, transformed_clip); + /* We know that we only have 1 plane at this point */ + texture = cogl_multi_plane_texture_get_plane (stex->texture, 0); + if (transformed_clip) texture = cogl_texture_new_from_sub_texture (texture, transformed_clip->x, diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c index bdc5501f5..a417e61d7 100644 --- a/src/compositor/meta-surface-actor-x11.c +++ b/src/compositor/meta-surface-actor-x11.c @@ -45,7 +45,7 @@ struct _MetaSurfaceActorX11 MetaDisplay *display; - CoglTexture *texture; + CoglMultiPlaneTexture *texture; Pixmap pixmap; Damage damage; @@ -129,8 +129,9 @@ set_pixmap (MetaSurfaceActorX11 *self, else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture)))) g_warning ("NOTE: Not using GLX TFP!\n"); - self->texture = texture; - meta_shaped_texture_set_texture (stex, texture); + self->texture = cogl_multi_plane_texture_new_single_plane (_cogl_texture_get_format (texture), + texture); + meta_shaped_texture_set_texture (stex, self->texture); } static void @@ -187,6 +188,7 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, int x, int y, int width, int height) { MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); + CoglTexture *texture; self->received_damage = TRUE; @@ -210,7 +212,8 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, if (!is_visible (self)) return; - cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (self->texture), + texture = cogl_multi_plane_texture_get_plane (self->texture, 0); + cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (texture), x, y, width, height); } diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index bcb6ce73a..417d30554 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -325,7 +325,8 @@ gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *self) { MetaShapedTexture *stex = meta_surface_actor_get_texture (self); - CoglTexture *texture = meta_shaped_texture_get_texture (stex); + CoglMultiPlaneTexture *mtex = meta_shaped_texture_get_texture (stex); + CoglTexture *texture; /* If we don't have a texture, like during initialization, assume * that we're ARGB32. @@ -335,9 +336,14 @@ meta_surface_actor_is_argb32 (MetaSurfaceActor *self) * place. This prevents us from continually redirecting and * unredirecting on every paint. */ - if (!texture) + if (!mtex) return !meta_surface_actor_is_unredirected (self); + /* Are we dealing with multiple planes? Then it can't be argb32 either */ + if (cogl_multi_plane_texture_get_n_planes (mtex) != 1) + return FALSE; + + texture = cogl_multi_plane_texture_get_plane (mtex, 0); switch (cogl_texture_get_components (texture)) { case COGL_TEXTURE_COMPONENTS_A: diff --git a/src/compositor/meta-texture-tower.c b/src/compositor/meta-texture-tower.c index 867fc16a4..f3102eec8 100644 --- a/src/compositor/meta-texture-tower.c +++ b/src/compositor/meta-texture-tower.c @@ -58,8 +58,8 @@ typedef struct struct _MetaTextureTower { int n_levels; - CoglTexture *textures[MAX_TEXTURE_LEVELS]; - CoglOffscreen *fbos[MAX_TEXTURE_LEVELS]; + CoglMultiPlaneTexture *textures[MAX_TEXTURE_LEVELS]; + GList *fbos[MAX_TEXTURE_LEVELS]; Box invalid[MAX_TEXTURE_LEVELS]; CoglPipeline *pipeline_template; }; @@ -112,8 +112,8 @@ meta_texture_tower_free (MetaTextureTower *tower) * unset or until the tower is freed. */ void -meta_texture_tower_set_base_texture (MetaTextureTower *tower, - CoglTexture *texture) +meta_texture_tower_set_base_texture (MetaTextureTower *tower, + CoglMultiPlaneTexture *texture) { int i; @@ -126,22 +126,14 @@ meta_texture_tower_set_base_texture (MetaTextureTower *tower, { for (i = 1; i < tower->n_levels; i++) { - if (tower->textures[i] != NULL) - { - cogl_object_unref (tower->textures[i]); - tower->textures[i] = NULL; - } - - if (tower->fbos[i] != NULL) - { - cogl_object_unref (tower->fbos[i]); - tower->fbos[i] = NULL; - } - } + cogl_clear_object (&tower->textures[i]); - cogl_object_unref (tower->textures[0]); + g_list_free_full (tower->fbos[i], cogl_object_unref); + tower->fbos[i] = NULL; + } } + cogl_clear_object (&tower->textures[0]); tower->textures[0] = texture; if (tower->textures[0] != NULL) @@ -150,8 +142,8 @@ meta_texture_tower_set_base_texture (MetaTextureTower *tower, cogl_object_ref (tower->textures[0]); - width = cogl_texture_get_width (tower->textures[0]); - height = cogl_texture_get_height (tower->textures[0]); + width = cogl_multi_plane_texture_get_width (tower->textures[0]); + height = cogl_multi_plane_texture_get_height (tower->textures[0]); tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height))); tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS); @@ -192,8 +184,8 @@ meta_texture_tower_update_area (MetaTextureTower *tower, if (tower->textures[0] == NULL) return; - texture_width = cogl_texture_get_width (tower->textures[0]); - texture_height = cogl_texture_get_height (tower->textures[0]); + texture_width = cogl_multi_plane_texture_get_width (tower->textures[0]); + texture_height = cogl_multi_plane_texture_get_height (tower->textures[0]); invalid.x1 = x; invalid.y1 = y; @@ -351,9 +343,27 @@ texture_tower_create_texture (MetaTextureTower *tower, int width, int height) { - tower->textures[level] = cogl_texture_new_with_size (width, height, - COGL_TEXTURE_NO_AUTO_MIPMAP, - TEXTURE_FORMAT); + CoglMultiPlaneTexture *base_tex = tower->textures[0]; + GPtrArray *planes; + uint8_t i, n_planes; + + n_planes = cogl_multi_plane_texture_get_n_planes (base_tex); + planes = g_ptr_array_new_full (n_planes, cogl_object_unref); + + for (i = 0; i < n_planes; i++) + { + CoglTexture *texture; + + texture = cogl_texture_new_with_size (width, height, + COGL_TEXTURE_NO_AUTO_MIPMAP, + TEXTURE_FORMAT); + g_ptr_array_add (planes, texture); + } + + tower->textures[level] = cogl_multi_plane_texture_new ( + cogl_multi_plane_texture_get_format (base_tex), + (CoglTexture **) g_ptr_array_free (planes, FALSE), + n_planes); tower->invalid[level].x1 = 0; tower->invalid[level].y1 = 0; @@ -365,50 +375,68 @@ static void texture_tower_revalidate (MetaTextureTower *tower, int level) { - CoglTexture *source_texture = tower->textures[level - 1]; - int source_texture_width = cogl_texture_get_width (source_texture); - int source_texture_height = cogl_texture_get_height (source_texture); - CoglTexture *dest_texture = tower->textures[level]; - int dest_texture_width = cogl_texture_get_width (dest_texture); - int dest_texture_height = cogl_texture_get_height (dest_texture); - Box *invalid = &tower->invalid[level]; - CoglFramebuffer *fb; - GError *catch_error = NULL; - CoglPipeline *pipeline; - - if (tower->fbos[level] == NULL) - tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture); - - fb = COGL_FRAMEBUFFER (tower->fbos[level]); - - if (!cogl_framebuffer_allocate (fb, &catch_error)) + CoglMultiPlaneTexture *src_tex = tower->textures[level - 1]; + int src_width = cogl_multi_plane_texture_get_width (src_tex); + int src_height = cogl_multi_plane_texture_get_height (src_tex); + uint8_t src_tex_n_planes = cogl_multi_plane_texture_get_n_planes (src_tex); + CoglMultiPlaneTexture *dest_tex = tower->textures[level]; + int dest_width = cogl_multi_plane_texture_get_width (dest_tex); + int dest_height = cogl_multi_plane_texture_get_height (dest_tex); + uint8_t i; + + + /* FIXME: cogl_offscreen_texture_new_with_texture doesn't work for + * multi-plane textures, so we have to make an FBO for each layer */ + for (i = 0; i < src_tex_n_planes; i++) { - g_error_free (catch_error); - return; - } + Box *invalid = &tower->invalid[level]; + CoglTexture *src_plane, *dest_plane; + CoglFramebuffer *fb; + GError *catch_error = NULL; + CoglPipeline *pipeline; - cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.); + src_plane = cogl_multi_plane_texture_get_plane (src_tex, i); + dest_plane = cogl_multi_plane_texture_get_plane (dest_tex, i); - if (!tower->pipeline_template) - { - CoglContext *ctx = - clutter_backend_get_cogl_context (clutter_get_default_backend ()); - tower->pipeline_template = cogl_pipeline_new (ctx); - cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL); - } + if (g_list_nth (tower->fbos[level], i) != NULL) + { + fb = COGL_FRAMEBUFFER (g_list_nth (tower->fbos[level], i)->data); + } + else + { + fb = COGL_FRAMEBUFFER (cogl_offscreen_new_with_texture (dest_plane)); + tower->fbos[level] = g_list_append (tower->fbos[level], fb); + } + + if (!cogl_framebuffer_allocate (fb, &catch_error)) + { + g_error_free (catch_error); + return; + } + + cogl_framebuffer_orthographic (fb, 0, 0, dest_width, dest_height, -1., 1.); + + if (!tower->pipeline_template) + { + CoglContext *ctx = + clutter_backend_get_cogl_context (clutter_get_default_backend ()); + tower->pipeline_template = cogl_pipeline_new (ctx); + cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL); + } - pipeline = cogl_pipeline_copy (tower->pipeline_template); - cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]); + pipeline = cogl_pipeline_copy (tower->pipeline_template); + cogl_pipeline_set_layer_texture (pipeline, 0, src_plane); - cogl_framebuffer_draw_textured_rectangle (fb, pipeline, - invalid->x1, invalid->y1, - invalid->x2, invalid->y2, - (2. * invalid->x1) / source_texture_width, - (2. * invalid->y1) / source_texture_height, - (2. * invalid->x2) / source_texture_width, - (2. * invalid->y2) / source_texture_height); + cogl_framebuffer_draw_textured_rectangle (fb, pipeline, + invalid->x1, invalid->y1, + invalid->x2, invalid->y2, + (2. * invalid->x1) / src_width, + (2. * invalid->y1) / src_height, + (2. * invalid->x2) / src_width, + (2. * invalid->y2) / src_height); - cogl_object_unref (pipeline); + cogl_object_unref (pipeline); + } tower->invalid[level].x1 = tower->invalid[level].x2 = 0; tower->invalid[level].y1 = tower->invalid[level].y2 = 0; @@ -427,7 +455,7 @@ texture_tower_revalidate (MetaTextureTower *tower, * Return value: the COGL texture handle to use for painting, or * %NULL if no base texture has yet been set. */ -CoglTexture * +CoglMultiPlaneTexture * meta_texture_tower_get_paint_texture (MetaTextureTower *tower) { int texture_width, texture_height; @@ -438,8 +466,8 @@ meta_texture_tower_get_paint_texture (MetaTextureTower *tower) if (tower->textures[0] == NULL) return NULL; - texture_width = cogl_texture_get_width (tower->textures[0]); - texture_height = cogl_texture_get_height (tower->textures[0]); + texture_width = cogl_multi_plane_texture_get_width (tower->textures[0]); + texture_height = cogl_multi_plane_texture_get_height (tower->textures[0]); level = get_paint_level(texture_width, texture_height); if (level < 0) /* singular paint matrix, scaled to nothing */ diff --git a/src/compositor/meta-texture-tower.h b/src/compositor/meta-texture-tower.h index 6a39e4184..9897d93b3 100644 --- a/src/compositor/meta-texture-tower.h +++ b/src/compositor/meta-texture-tower.h @@ -53,14 +53,14 @@ typedef struct _MetaTextureTower MetaTextureTower; MetaTextureTower *meta_texture_tower_new (void); void meta_texture_tower_free (MetaTextureTower *tower); -void meta_texture_tower_set_base_texture (MetaTextureTower *tower, - CoglTexture *texture); +void meta_texture_tower_set_base_texture (MetaTextureTower *tower, + CoglMultiPlaneTexture *texture); void meta_texture_tower_update_area (MetaTextureTower *tower, int x, int y, int width, int height); -CoglTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower); +CoglMultiPlaneTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower); G_END_DECLS diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 2588c74e4..3a30c0caa 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -1502,7 +1502,8 @@ build_and_scan_frame_mask (MetaWindowActor *self, guchar *mask_data; guint tex_width, tex_height; MetaShapedTexture *stex; - CoglTexture *paint_tex, *mask_texture; + CoglMultiPlaneTexture *paint_tex; + CoglTexture *mask_texture; int stride; cairo_t *cr; cairo_surface_t *surface; @@ -1517,8 +1518,8 @@ build_and_scan_frame_mask (MetaWindowActor *self, if (paint_tex == NULL) return; - tex_width = cogl_texture_get_width (paint_tex); - tex_height = cogl_texture_get_height (paint_tex); + tex_width = cogl_multi_plane_texture_get_width (paint_tex); + tex_height = cogl_multi_plane_texture_get_height (paint_tex); stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8, tex_width); diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h index c36b8547f..dd4548cb5 100644 --- a/src/meta/meta-shaped-texture.h +++ b/src/meta/meta-shaped-texture.h @@ -52,7 +52,7 @@ gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex, int height); META_EXPORT -CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex); +CoglMultiPlaneTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex); META_EXPORT void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c index 0f191a0d8..a6ff7cf88 100644 --- a/src/wayland/meta-wayland-buffer.c +++ b/src/wayland/meta-wayland-buffer.c @@ -123,7 +123,7 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer) stream = meta_wayland_egl_stream_new (buffer, NULL); if (stream) { - CoglTexture2D *texture; + CoglMultiPlaneTexture *texture; texture = meta_wayland_egl_stream_create_texture (stream, NULL); if (!texture) @@ -131,7 +131,7 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer) buffer->egl_stream.stream = stream; buffer->type = META_WAYLAND_BUFFER_TYPE_EGL_STREAM; - buffer->egl_stream.texture = COGL_TEXTURE (texture); + buffer->egl_stream.texture = texture; buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream); return TRUE; @@ -163,43 +163,78 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer, CoglTextureComponents *components_out) { CoglPixelFormat format; - CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA; switch (wl_shm_buffer_get_format (shm_buffer)) { #if G_BYTE_ORDER == G_BIG_ENDIAN case WL_SHM_FORMAT_ARGB8888: format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; + components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA; break; case WL_SHM_FORMAT_XRGB8888: format = COGL_PIXEL_FORMAT_ARGB_8888; - components = COGL_TEXTURE_COMPONENTS_RGB; + components_out[0] = COGL_TEXTURE_COMPONENTS_RGB; break; #elif G_BYTE_ORDER == G_LITTLE_ENDIAN case WL_SHM_FORMAT_ARGB8888: format = COGL_PIXEL_FORMAT_BGRA_8888_PRE; + components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA; break; case WL_SHM_FORMAT_XRGB8888: format = COGL_PIXEL_FORMAT_BGRA_8888; - components = COGL_TEXTURE_COMPONENTS_RGB; + components_out[0] = COGL_TEXTURE_COMPONENTS_RGB; break; #endif + case WL_SHM_FORMAT_NV12: + format = COGL_PIXEL_FORMAT_NV12; + components_out[0] = COGL_TEXTURE_COMPONENTS_R; + components_out[1] = COGL_TEXTURE_COMPONENTS_RG; + break; + case WL_SHM_FORMAT_NV21: + format = COGL_PIXEL_FORMAT_NV21; + components_out[0] = COGL_TEXTURE_COMPONENTS_R; + components_out[1] = COGL_TEXTURE_COMPONENTS_RG; + break; + case WL_SHM_FORMAT_YUV422: + format = COGL_PIXEL_FORMAT_YUV422; + components_out[0] = COGL_TEXTURE_COMPONENTS_R; + components_out[1] = COGL_TEXTURE_COMPONENTS_R; + components_out[2] = COGL_TEXTURE_COMPONENTS_R; + break; + case WL_SHM_FORMAT_YVU422: + format = COGL_PIXEL_FORMAT_YVU422; + components_out[0] = COGL_TEXTURE_COMPONENTS_R; + components_out[1] = COGL_TEXTURE_COMPONENTS_R; + components_out[2] = COGL_TEXTURE_COMPONENTS_R; + break; + case WL_SHM_FORMAT_YUV444: + format = COGL_PIXEL_FORMAT_YUV444; + components_out[0] = COGL_TEXTURE_COMPONENTS_R; + components_out[1] = COGL_TEXTURE_COMPONENTS_R; + components_out[2] = COGL_TEXTURE_COMPONENTS_R; + break; + case WL_SHM_FORMAT_YVU444: + format = COGL_PIXEL_FORMAT_YVU444; + components_out[0] = COGL_TEXTURE_COMPONENTS_R; + components_out[1] = COGL_TEXTURE_COMPONENTS_R; + components_out[2] = COGL_TEXTURE_COMPONENTS_R; + break; + default: g_warn_if_reached (); format = COGL_PIXEL_FORMAT_ARGB_8888; + components_out[0] = COGL_TEXTURE_COMPONENTS_RGBA; } if (format_out) *format_out = format; - if (components_out) - *components_out = components; } static gboolean -shm_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - gboolean *changed_texture, - GError **error) +shm_buffer_attach (MetaWaylandBuffer *buffer, + CoglMultiPlaneTexture **texture, + gboolean *changed_texture, + GError **error) { MetaBackend *backend = meta_get_backend (); ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); @@ -207,21 +242,30 @@ shm_buffer_attach (MetaWaylandBuffer *buffer, struct wl_shm_buffer *shm_buffer; int stride, width, height; CoglPixelFormat format; - CoglTextureComponents components; - CoglBitmap *bitmap; - CoglTexture *new_texture; - + CoglTextureComponents components[3]; + guint i, n_planes; + uint8_t h_factors[3], v_factors[3], bpp[3]; + CoglPixelFormat subformats[3]; + gsize plane_offset = 0; + guint8 *data; + GPtrArray *planes; + + /* Query the necessary parameters */ shm_buffer = wl_shm_buffer_get (buffer->resource); stride = wl_shm_buffer_get_stride (shm_buffer); width = wl_shm_buffer_get_width (shm_buffer); height = wl_shm_buffer_get_height (shm_buffer); - shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components); + shm_buffer_get_cogl_pixel_format (shm_buffer, &format, components); + n_planes = cogl_pixel_format_get_n_planes (format); + cogl_pixel_format_get_subsampling_factors (format, h_factors, v_factors); + cogl_pixel_format_get_subformats (format, subformats); + cogl_pixel_format_get_bytes_per_pixel (format, bpp); if (*texture && - cogl_texture_get_width (*texture) == width && - cogl_texture_get_height (*texture) == height && - cogl_texture_get_components (*texture) == components && - _cogl_texture_get_format (*texture) == format) + cogl_multi_plane_texture_get_width (*texture) == width && + cogl_multi_plane_texture_get_height (*texture) == height && + /*XXX cogl_texture_get_components (*texture) == components && */ + cogl_multi_plane_texture_get_format (*texture) == format) { buffer->is_y_inverted = TRUE; *changed_texture = FALSE; @@ -230,56 +274,92 @@ shm_buffer_attach (MetaWaylandBuffer *buffer, cogl_clear_object (texture); + /* Safely access the data inside the buffer */ wl_shm_buffer_begin_access (shm_buffer); + data = wl_shm_buffer_get_data (shm_buffer); - bitmap = cogl_bitmap_new_for_data (cogl_context, - width, height, - format, - stride, - wl_shm_buffer_get_data (shm_buffer)); - - new_texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap)); - cogl_texture_set_components (new_texture, components); - - if (!cogl_texture_allocate (new_texture, error)) + planes = g_ptr_array_new_full (n_planes, cogl_object_unref); + for (i = 0; i < n_planes; i++) { - g_clear_pointer (&new_texture, cogl_object_unref); - if (g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE)) + int plane_stride; + CoglBitmap *plane_bitmap; + CoglTexture *plane_texture; + + /* Adjust the stride: map to the amount of pixels and calculate how many + * bytes that takes in the current plane */ + plane_stride = (stride / bpp[0]) * bpp[i] / h_factors[i]; + + /* Define the bitmap that of this plane */ + plane_bitmap = cogl_bitmap_new_for_data (cogl_context, + width / h_factors[i], + height / v_factors[i], + subformats[i], + plane_stride, + data + plane_offset); + g_assert (plane_bitmap); + + /* Create a texture out of it so we can upload it to the GPU */ + plane_texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (plane_bitmap)); + + /* Separately set the components (necessary for e.g. XRGB, NV12) */ + cogl_texture_set_components (plane_texture, components[i]); + + if (!cogl_texture_allocate (plane_texture, error)) { CoglTexture2DSliced *texture_sliced; + cogl_clear_object (&plane_texture); + + /* If it didn't work due to an NPOT size, try again with an atlas texture */ + if (!g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE)) + { + cogl_object_unref (plane_bitmap); + goto failure; + } + g_clear_error (error); texture_sliced = - cogl_texture_2d_sliced_new_from_bitmap (bitmap, + cogl_texture_2d_sliced_new_from_bitmap (plane_bitmap, COGL_TEXTURE_MAX_WASTE); - new_texture = COGL_TEXTURE (texture_sliced); - cogl_texture_set_components (new_texture, components); + plane_texture = COGL_TEXTURE (texture_sliced); + + cogl_texture_set_components (plane_texture, components[i]); - if (!cogl_texture_allocate (new_texture, error)) - g_clear_pointer (&new_texture, cogl_object_unref); + if (!cogl_texture_allocate (plane_texture, error)) + { + cogl_clear_object (&plane_texture); + goto failure; + } } + + g_ptr_array_add (planes, plane_texture); + + /* Calculate the next plane start in the buffer (consider subsampling) */ + plane_offset += plane_stride * (height / v_factors[i]); } - cogl_object_unref (bitmap); + *texture = cogl_multi_plane_texture_new (format, + (CoglTexture **) g_ptr_array_free (planes, FALSE), + n_planes); wl_shm_buffer_end_access (shm_buffer); - if (!new_texture) - return FALSE; - - *texture = new_texture; *changed_texture = TRUE; buffer->is_y_inverted = TRUE; return TRUE; + +failure: + *texture = NULL; + return FALSE; } static gboolean -egl_image_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - gboolean *changed_texture, - GError **error) +egl_image_buffer_attach (MetaWaylandBuffer *buffer, + CoglMultiPlaneTexture **texture, + gboolean *changed_texture, + GError **error) { MetaBackend *backend = meta_get_backend (); MetaEgl *egl = meta_backend_get_egl (backend); @@ -288,8 +368,9 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer, EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); int format, width, height, y_inverted; CoglPixelFormat cogl_format; - EGLImageKHR egl_image; - CoglTexture2D *texture_2d; + CoglTextureComponents components[3]; + guint i, n_planes; + GPtrArray *planes; if (buffer->egl_image.texture) { @@ -299,6 +380,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer, return TRUE; } + /* Query the necessary properties */ if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource, EGL_TEXTURE_FORMAT, &format, error)) @@ -319,6 +401,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer, NULL)) y_inverted = EGL_TRUE; + /* Map the EGL texture format to CoglPixelFormat, if possible */ switch (format) { case EGL_TEXTURE_RGB: @@ -327,6 +410,12 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer, case EGL_TEXTURE_RGBA: cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; break; + case EGL_TEXTURE_Y_UV_WL: + cogl_format = COGL_PIXEL_FORMAT_NV12; + break; + case EGL_TEXTURE_Y_U_V_WL: + cogl_format = COGL_PIXEL_FORMAT_YUV444; + break; default: g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, @@ -334,27 +423,51 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer, return FALSE; } - /* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be used - * in conjunction with the EGL_WAYLAND_BUFFER_WL target. */ - egl_image = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT, - EGL_WAYLAND_BUFFER_WL, buffer->resource, - NULL, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - return FALSE; + n_planes = cogl_pixel_format_get_n_planes (cogl_format); + cogl_pixel_format_get_cogl_components (cogl_format, components); + planes = g_ptr_array_new_full (n_planes, cogl_object_unref); - texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context, - width, height, - cogl_format, - egl_image, - error); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); + /* Each EGLImage is a plane in the final texture */ + for (i = 0; i < n_planes; i++) + { + EGLint egl_attribs[3]; + EGLImageKHR egl_img; + CoglTexture2D *texture_2d; + + /* Specify that we want the i'th plane */ + egl_attribs[0] = EGL_WAYLAND_PLANE_WL; + egl_attribs[1] = i; + egl_attribs[2] = EGL_NONE; + + /* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be + * used in conjunction with the EGL_WAYLAND_BUFFER_WL target. */ + egl_img = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT, + EGL_WAYLAND_BUFFER_WL, buffer->resource, + egl_attribs, + error); + + if (G_UNLIKELY (egl_img == EGL_NO_IMAGE_KHR)) + goto on_error; + + texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context, + width, height, + cogl_format, + components[i], + egl_img, + error); + + meta_egl_destroy_image (egl, egl_display, egl_img, NULL); + + if (G_UNLIKELY (!texture_2d)) + goto on_error; + + g_ptr_array_add (planes, texture_2d); + } - if (!texture_2d) - return FALSE; - buffer->egl_image.texture = COGL_TEXTURE (texture_2d); + buffer->egl_image.texture = cogl_multi_plane_texture_new (cogl_format, + (CoglTexture **) g_ptr_array_free (planes, FALSE), + n_planes); buffer->is_y_inverted = !!y_inverted; cogl_clear_object (texture); @@ -362,14 +475,19 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer, *changed_texture = TRUE; return TRUE; + +on_error: + g_ptr_array_free (planes, TRUE); + + return FALSE; } #ifdef HAVE_WAYLAND_EGLSTREAM static gboolean -egl_stream_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - gboolean *changed_texture, - GError **error) +egl_stream_buffer_attach (MetaWaylandBuffer *buffer, + CoglMultiPlaneTexture **texture, + gboolean *changed_texture, + GError **error) { MetaWaylandEglStream *stream = buffer->egl_stream.stream; @@ -406,10 +524,10 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer, * meta_wayland_buffer_attach(), which also might free it, as described above. */ gboolean -meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - gboolean *changed_texture, - GError **error) +meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, + CoglMultiPlaneTexture **texture, + gboolean *changed_texture, + GError **error) { g_return_val_if_fail (buffer->resource, FALSE); @@ -466,55 +584,94 @@ meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer) } static gboolean -process_shm_buffer_damage (MetaWaylandBuffer *buffer, - CoglTexture *texture, - cairo_region_t *region, - GError **error) +process_shm_buffer_damage (MetaWaylandBuffer *buffer, + CoglMultiPlaneTexture *texture, + cairo_region_t *region, + GError **error) { struct wl_shm_buffer *shm_buffer; - int i, n_rectangles; gboolean set_texture_failed = FALSE; + CoglPixelFormat format; + CoglTextureComponents components[3]; + uint8_t h_factors[3], v_factors[3], bpp[3]; + CoglPixelFormat subformats[3]; + gsize plane_offset = 0; + const uint8_t *data; + int32_t stride, height; + uint8_t i, n_planes; + int j, n_rectangles; n_rectangles = cairo_region_num_rectangles (region); shm_buffer = wl_shm_buffer_get (buffer->resource); + + /* Get the data */ wl_shm_buffer_begin_access (shm_buffer); + data = wl_shm_buffer_get_data (shm_buffer); + + /* Query the necessary properties */ + stride = wl_shm_buffer_get_stride (shm_buffer); + height = wl_shm_buffer_get_height (shm_buffer); + shm_buffer_get_cogl_pixel_format (shm_buffer, &format, components); - for (i = 0; i < n_rectangles; i++) + /* Fetch some properties from the pixel format */ + n_planes = cogl_multi_plane_texture_get_n_planes (texture); + cogl_pixel_format_get_subformats (format, subformats); + cogl_pixel_format_get_subsampling_factors (format, h_factors, v_factors); + cogl_pixel_format_get_bytes_per_pixel (format, bpp); + + for (i = 0; i < n_planes; i++) { - const uint8_t *data = wl_shm_buffer_get_data (shm_buffer); - int32_t stride = wl_shm_buffer_get_stride (shm_buffer); - CoglPixelFormat format; - int bpp; - cairo_rectangle_int_t rect; - - shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL); - bpp = cogl_pixel_format_get_bytes_per_pixel_simple (format); - cairo_region_get_rectangle (region, i, &rect); - - if (!_cogl_texture_set_region (texture, - rect.width, rect.height, - format, - stride, - data + rect.x * bpp + rect.y * stride, - rect.x, rect.y, - 0, - error)) + CoglTexture *plane; + int plane_stride; + + plane = cogl_multi_plane_texture_get_plane (texture, i); + plane_stride = (stride / bpp[0]) * bpp[i] / h_factors[i]; + + for (j = 0; j < n_rectangles; j++) { - set_texture_failed = TRUE; - break; + cairo_rectangle_int_t rect; + gsize rect_offset; + + cairo_region_get_rectangle (region, j, &rect); + + /* It's possible we get a faulty rectangle of size zero: ignore */ + if (rect.height == 0 || rect.width == 0) + continue; + + rect_offset = plane_offset + + rect.y * plane_stride / v_factors[i] /* Find the right row */ + + rect.x * bpp[i] / h_factors[i]; /* and the right column */ + + if (!_cogl_texture_set_region (plane, + rect.width / h_factors[i], + rect.height / v_factors[i], + subformats[i], + plane_stride, + data + rect_offset, + rect.x, rect.y, + 0, + error)) + { + set_texture_failed = TRUE; + goto out; + } } + + /* Calculate the next plane start in the buffer (consider subsampling) */ + plane_offset += plane_stride * (height / v_factors[i]); } +out: wl_shm_buffer_end_access (shm_buffer); return !set_texture_failed; } void -meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer, - CoglTexture *texture, - cairo_region_t *region) +meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer, + CoglMultiPlaneTexture *texture, + cairo_region_t *region) { gboolean res = FALSE; GError *error = NULL; diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h index 5d75a3451..07522f27b 100644 --- a/src/wayland/meta-wayland-buffer.h +++ b/src/wayland/meta-wayland-buffer.h @@ -56,19 +56,19 @@ struct _MetaWaylandBuffer MetaWaylandBufferType type; struct { - CoglTexture *texture; + CoglMultiPlaneTexture *texture; } egl_image; #ifdef HAVE_WAYLAND_EGLSTREAM struct { MetaWaylandEglStream *stream; - CoglTexture *texture; + CoglMultiPlaneTexture *texture; } egl_stream; #endif struct { MetaWaylandDmaBufBuffer *dma_buf; - CoglTexture *texture; + CoglMultiPlaneTexture *texture; } dma_buf; }; @@ -80,14 +80,14 @@ MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resou struct wl_resource * meta_wayland_buffer_get_resource (MetaWaylandBuffer *buffer); gboolean meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer); gboolean meta_wayland_buffer_realize (MetaWaylandBuffer *buffer); -gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - gboolean *changed_texture, - GError **error); +gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, + CoglMultiPlaneTexture **texture, + gboolean *changed_texture, + GError **error); CoglSnippet * meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer); gboolean meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer); void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer, - CoglTexture *texture, + CoglMultiPlaneTexture *texture, cairo_region_t *region); #endif /* META_WAYLAND_BUFFER_H */ diff --git a/src/wayland/meta-wayland-cursor-surface.c b/src/wayland/meta-wayland-cursor-surface.c index 76268d5f2..5e31db239 100644 --- a/src/wayland/meta-wayland-cursor-surface.c +++ b/src/wayland/meta-wayland-cursor-surface.c @@ -58,7 +58,7 @@ update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface) MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (cursor_surface)); MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (priv->cursor_sprite); - CoglTexture *texture; + CoglMultiPlaneTexture *texture; if (!priv->cursor_renderer) return; @@ -66,8 +66,13 @@ update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface) texture = meta_wayland_surface_get_texture (surface); if (texture) { + CoglTexture *plane; + + /* XXX We assume that we get a simple (single-plane) texture here */ + plane = cogl_multi_plane_texture_get_plane (texture, 0); + meta_cursor_sprite_set_texture (cursor_sprite, - texture, + plane, priv->hot_x * surface->scale, priv->hot_y * surface->scale); } diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c index e49fba9cf..04a35f239 100644 --- a/src/wayland/meta-wayland-dma-buf.c +++ b/src/wayland/meta-wayland-dma-buf.c @@ -56,8 +56,9 @@ struct _MetaWaylandDmaBufBuffer int width; int height; uint32_t drm_format; - uint64_t drm_modifier; bool is_y_inverted; + + uint64_t drm_modifier[META_WAYLAND_DMA_BUF_MAX_FDS]; int fds[META_WAYLAND_DMA_BUF_MAX_FDS]; int offsets[META_WAYLAND_DMA_BUF_MAX_FDS]; unsigned int strides[META_WAYLAND_DMA_BUF_MAX_FDS]; @@ -65,25 +66,9 @@ struct _MetaWaylandDmaBufBuffer G_DEFINE_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer, G_TYPE_OBJECT); -static gboolean -meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, - GError **error) +static CoglPixelFormat +drm_buffer_get_cogl_pixel_format (MetaWaylandDmaBufBuffer *dma_buf) { - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - MetaWaylandDmaBufBuffer *dma_buf = buffer->dma_buf.dma_buf; - CoglPixelFormat cogl_format; - EGLImageKHR egl_image; - CoglTexture2D *texture; - EGLint attribs[64]; - int attr_idx = 0; - - if (buffer->dma_buf.texture) - return TRUE; - switch (dma_buf->drm_format) { /* @@ -94,30 +79,62 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, * and access the buffer memory at all. */ case DRM_FORMAT_XRGB8888: - cogl_format = COGL_PIXEL_FORMAT_RGB_888; - break; + return COGL_PIXEL_FORMAT_RGB_888; case DRM_FORMAT_ARGB8888: - cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; - break; + return COGL_PIXEL_FORMAT_ARGB_8888_PRE; case DRM_FORMAT_ARGB2101010: - cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE; - break; + return COGL_PIXEL_FORMAT_ARGB_2101010_PRE; case DRM_FORMAT_RGB565: - cogl_format = COGL_PIXEL_FORMAT_RGB_565; - break; + return COGL_PIXEL_FORMAT_RGB_565; + case DRM_FORMAT_YUYV: + return COGL_PIXEL_FORMAT_YUYV; + case DRM_FORMAT_NV12: + return COGL_PIXEL_FORMAT_NV12; + case DRM_FORMAT_NV21: + return COGL_PIXEL_FORMAT_NV21; + case DRM_FORMAT_YUV410: + return COGL_PIXEL_FORMAT_YUV410; + case DRM_FORMAT_YVU410: + return COGL_PIXEL_FORMAT_YVU410; + case DRM_FORMAT_YUV411: + return COGL_PIXEL_FORMAT_YUV411; + case DRM_FORMAT_YVU411: + return COGL_PIXEL_FORMAT_YVU411; + case DRM_FORMAT_YUV420: + return COGL_PIXEL_FORMAT_YUV420; + case DRM_FORMAT_YVU420: + return COGL_PIXEL_FORMAT_YVU420; + case DRM_FORMAT_YUV422: + return COGL_PIXEL_FORMAT_YUV422; + case DRM_FORMAT_YVU422: + return COGL_PIXEL_FORMAT_YVU422; + case DRM_FORMAT_YUV444: + return COGL_PIXEL_FORMAT_YUV444; + case DRM_FORMAT_YVU444: + return COGL_PIXEL_FORMAT_YVU444; default: - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Unsupported buffer format %d", dma_buf->drm_format); - return FALSE; + return COGL_PIXEL_FORMAT_ANY; } +} + +static EGLImageKHR +create_egl_image_from_dmabuf (MetaEgl *egl, + EGLDisplay egl_display, + MetaWaylandDmaBufBuffer *dma_buf, + int32_t width, + int32_t height, + uint32_t drm_format, + GError **error) +{ + EGLint attribs[64]; + int attr_idx = 0; attribs[attr_idx++] = EGL_WIDTH; - attribs[attr_idx++] = dma_buf->width; + attribs[attr_idx++] = width; attribs[attr_idx++] = EGL_HEIGHT; - attribs[attr_idx++] = dma_buf->height; + attribs[attr_idx++] = height; attribs[attr_idx++] = EGL_LINUX_DRM_FOURCC_EXT; - attribs[attr_idx++] = dma_buf->drm_format; + attribs[attr_idx++] = drm_format; attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_FD_EXT; attribs[attr_idx++] = dma_buf->fds[0]; @@ -126,9 +143,9 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; attribs[attr_idx++] = dma_buf->strides[0]; attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT; - attribs[attr_idx++] = dma_buf->drm_modifier & 0xffffffff; + attribs[attr_idx++] = dma_buf->drm_modifier[0] & 0xffffffff; attribs[attr_idx++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT; - attribs[attr_idx++] = dma_buf->drm_modifier >> 32; + attribs[attr_idx++] = dma_buf->drm_modifier[0] >> 32; if (dma_buf->fds[1] >= 0) { @@ -139,9 +156,9 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; attribs[attr_idx++] = dma_buf->strides[1]; attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT; - attribs[attr_idx++] = dma_buf->drm_modifier & 0xffffffff; + attribs[attr_idx++] = dma_buf->drm_modifier[1] & 0xffffffff; attribs[attr_idx++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT; - attribs[attr_idx++] = dma_buf->drm_modifier >> 32; + attribs[attr_idx++] = dma_buf->drm_modifier[1] >> 32; } if (dma_buf->fds[2] >= 0) @@ -153,9 +170,9 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_PITCH_EXT; attribs[attr_idx++] = dma_buf->strides[2]; attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT; - attribs[attr_idx++] = dma_buf->drm_modifier & 0xffffffff; + attribs[attr_idx++] = dma_buf->drm_modifier[2] & 0xffffffff; attribs[attr_idx++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT; - attribs[attr_idx++] = dma_buf->drm_modifier >> 32; + attribs[attr_idx++] = dma_buf->drm_modifier[2] >> 32; } if (dma_buf->fds[3] >= 0) @@ -167,46 +184,101 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_PITCH_EXT; attribs[attr_idx++] = dma_buf->strides[3]; attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT; - attribs[attr_idx++] = dma_buf->drm_modifier & 0xffffffff; + attribs[attr_idx++] = dma_buf->drm_modifier[3] & 0xffffffff; attribs[attr_idx++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT; - attribs[attr_idx++] = dma_buf->drm_modifier >> 32; + attribs[attr_idx++] = dma_buf->drm_modifier[3] >> 32; } attribs[attr_idx++] = EGL_NONE; - attribs[attr_idx++] = EGL_NONE; - /* The EXT_image_dma_buf_import spec states that EGL_NO_CONTEXT is to be used - * in conjunction with the EGL_LINUX_DMA_BUF_EXT target. Similarly, the - * native buffer is named in the attribs. */ - egl_image = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT, - EGL_LINUX_DMA_BUF_EXT, NULL, attribs, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - return FALSE; + /* The EXT_image_dma_buf_import spec states that EGL_NO_CONTEXT is to be + * used in conjunction with the EGL_LINUX_DMA_BUF_EXT target. Similarly, + * the native buffer is named in the attribs. */ + return meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT, + EGL_LINUX_DMA_BUF_EXT, NULL, attribs, + error); +} - texture = cogl_egl_texture_2d_new_from_image (cogl_context, - dma_buf->width, - dma_buf->height, - cogl_format, - egl_image, - error); +static gboolean +meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, + GError **error) +{ + MetaBackend *backend = meta_get_backend (); + MetaEgl *egl = meta_backend_get_egl (backend); + ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); + CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); + EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); + MetaWaylandDmaBufBuffer *dma_buf = buffer->dma_buf.dma_buf; + CoglPixelFormat cogl_format; + CoglTextureComponents components[3]; + CoglPixelFormat subformats[3]; + GPtrArray *planes; + guint i = 0, n_planes = 1; - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); + if (buffer->dma_buf.texture) + return TRUE; - if (!texture) - return FALSE; + cogl_format = drm_buffer_get_cogl_pixel_format (dma_buf); + if (cogl_format == COGL_PIXEL_FORMAT_ANY) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Unsupported buffer format %d", dma_buf->drm_format); + return FALSE; + } + + n_planes = cogl_pixel_format_get_n_planes (cogl_format); + cogl_pixel_format_get_subformats (cogl_format, subformats); + cogl_pixel_format_get_cogl_components (cogl_format, components); + planes = g_ptr_array_new_full (n_planes, cogl_object_unref); - buffer->dma_buf.texture = COGL_TEXTURE (texture); + /* Each EGLImage is a plane in the final CoglMultiPlaneTexture */ + for (i = 0; i < n_planes; i++) + { + EGLImageKHR egl_img; + CoglTexture2D *plane; + + egl_img = create_egl_image_from_dmabuf (egl, + egl_display, + dma_buf, + dma_buf->width, dma_buf->height, + dma_buf->drm_format, + error); + if (egl_img == EGL_NO_IMAGE_KHR) + goto on_error; + + plane = cogl_egl_texture_2d_new_from_image (cogl_context, + dma_buf->width, + dma_buf->height, + subformats[i], + components[i], + egl_img, + error); + + meta_egl_destroy_image (egl, egl_display, egl_img, NULL); + + if (!plane) + goto on_error; + + g_ptr_array_add (planes, plane); + } + + buffer->dma_buf.texture = cogl_multi_plane_texture_new (cogl_format, + (CoglTexture **) g_ptr_array_free (planes, FALSE), + n_planes); buffer->is_y_inverted = dma_buf->is_y_inverted; return TRUE; + +on_error: + g_ptr_array_free (planes, TRUE); + return FALSE; } gboolean -meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - gboolean *changed_texture, - GError **error) +meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer, + CoglMultiPlaneTexture **texture, + gboolean *changed_texture, + GError **error) { if (!meta_wayland_dma_buf_realize_texture (buffer, error)) return FALSE; @@ -260,8 +332,8 @@ buffer_params_add (struct wl_client *client, return; } - if (dma_buf->drm_modifier != DRM_FORMAT_MOD_INVALID && - dma_buf->drm_modifier != drm_modifier) + if (dma_buf->drm_modifier[plane_idx] != DRM_FORMAT_MOD_INVALID && + dma_buf->drm_modifier[plane_idx] != drm_modifier) { wl_resource_post_error (resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER, @@ -269,8 +341,9 @@ buffer_params_add (struct wl_client *client, return; } - dma_buf->drm_modifier = drm_modifier; + dma_buf->fds[plane_idx] = fd; + dma_buf->drm_modifier[plane_idx] = drm_modifier; dma_buf->offsets[plane_idx] = offset; dma_buf->strides[plane_idx] = stride; } @@ -550,6 +623,9 @@ dma_buf_bind (struct wl_client *client, send_modifiers (resource, DRM_FORMAT_XRGB8888); send_modifiers (resource, DRM_FORMAT_ARGB2101010); send_modifiers (resource, DRM_FORMAT_RGB565); + send_modifiers (resource, DRM_FORMAT_AYUV); + send_modifiers (resource, DRM_FORMAT_NV12); + send_modifiers (resource, DRM_FORMAT_YUV422); } gboolean @@ -598,10 +674,12 @@ meta_wayland_dma_buf_buffer_init (MetaWaylandDmaBufBuffer *dma_buf) { int i; - dma_buf->drm_modifier = DRM_FORMAT_MOD_INVALID; for (i = 0; i < META_WAYLAND_DMA_BUF_MAX_FDS; i++) - dma_buf->fds[i] = -1; + { + dma_buf->drm_modifier[i] = DRM_FORMAT_MOD_INVALID; + dma_buf->fds[i] = -1; + } } static void diff --git a/src/wayland/meta-wayland-dma-buf.h b/src/wayland/meta-wayland-dma-buf.h index 580a3e777..a2b4fd937 100644 --- a/src/wayland/meta-wayland-dma-buf.h +++ b/src/wayland/meta-wayland-dma-buf.h @@ -42,10 +42,10 @@ typedef struct _MetaWaylandDmaBufBuffer MetaWaylandDmaBufBuffer; gboolean meta_wayland_dma_buf_init (MetaWaylandCompositor *compositor); gboolean -meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - gboolean *changed_texture, - GError **error); +meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer, + CoglMultiPlaneTexture **texture, + gboolean *changed_texture, + GError **error); MetaWaylandDmaBufBuffer * meta_wayland_dma_buf_from_buffer (MetaWaylandBuffer *buffer); diff --git a/src/wayland/meta-wayland-egl-stream.c b/src/wayland/meta-wayland-egl-stream.c index 3f8908e67..a0125894d 100644 --- a/src/wayland/meta-wayland-egl-stream.c +++ b/src/wayland/meta-wayland-egl-stream.c @@ -132,7 +132,7 @@ struct _MetaWaylandEglStream EGLStreamKHR egl_stream; MetaWaylandBuffer *buffer; - CoglTexture2D *texture; + CoglMultiPlaneTexture *texture; gboolean is_y_inverted; }; @@ -183,7 +183,7 @@ stream_texture_destroyed (gpointer data) } static gboolean -alloc_egl_stream_texture (CoglTexture2D *texture, +alloc_egl_stream_texture (CoglTexture2D *texture_2d, gpointer user_data, GError **error) { @@ -199,7 +199,7 @@ alloc_egl_stream_texture (CoglTexture2D *texture, error); } -CoglTexture2D * +CoglMultiPlaneTexture * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream, GError **error) { @@ -208,7 +208,7 @@ meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream, ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - CoglTexture2D *texture; + CoglTexture2D *texture_2d; int width, height; int y_inverted; @@ -230,29 +230,30 @@ meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream, NULL)) y_inverted = EGL_TRUE; - texture = + texture_2d = cogl_texture_2d_new_from_egl_image_external (cogl_context, width, height, alloc_egl_stream_texture, g_object_ref (stream), stream_texture_destroyed, error); - if (!texture) + if (!texture_2d) { g_object_unref (stream); return NULL; } - if (!cogl_texture_allocate (COGL_TEXTURE (texture), error)) + if (!cogl_texture_allocate (COGL_TEXTURE (texture_2d), error)) { - cogl_object_unref (texture); + cogl_object_unref (texture_2d); return NULL; } - stream->texture = texture; + stream->texture = cogl_multi_plane_texture_new_single_plane (COGL_PIXEL_FORMAT_ANY, + COGL_TEXTURE (texture_2d)); stream->is_y_inverted = !!y_inverted; - return texture; + return stream->texture; } gboolean diff --git a/src/wayland/meta-wayland-egl-stream.h b/src/wayland/meta-wayland-egl-stream.h index fe488ed54..d548d9a72 100644 --- a/src/wayland/meta-wayland-egl-stream.h +++ b/src/wayland/meta-wayland-egl-stream.h @@ -45,8 +45,8 @@ MetaWaylandEglStream * meta_wayland_egl_stream_new (MetaWaylandBuffer *buffer, gboolean meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream, GError **error); -CoglTexture2D * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream, - GError **error); +CoglMultiPlaneTexture * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream, + GError **error); CoglSnippet * meta_wayland_egl_stream_create_snippet (void); gboolean meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream); diff --git a/src/wayland/meta-wayland-shell-surface.c b/src/wayland/meta-wayland-shell-surface.c index f8354ab7c..3a8e336a4 100644 --- a/src/wayland/meta-wayland-shell-surface.c +++ b/src/wayland/meta-wayland-shell-surface.c @@ -153,7 +153,7 @@ meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole *surface_role MetaWaylandSurfaceRoleClass *surface_role_class; MetaWindow *window; MetaWaylandBuffer *buffer; - CoglTexture *texture; + CoglMultiPlaneTexture *texture; double scale; surface_role_class = @@ -171,8 +171,8 @@ meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole *surface_role scale = meta_wayland_actor_surface_calculate_scale (actor_surface); texture = meta_wayland_surface_get_texture (surface); - window->buffer_rect.width = cogl_texture_get_width (texture) * scale; - window->buffer_rect.height = cogl_texture_get_height (texture) * scale; + window->buffer_rect.width = cogl_multi_plane_texture_get_width (texture) * scale; + window->buffer_rect.height = cogl_multi_plane_texture_get_height (texture) * scale; } static void diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index f63d6d876..c72ff3c71 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -246,7 +246,7 @@ get_buffer_width (MetaWaylandSurface *surface) MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); if (buffer) - return cogl_texture_get_width (surface->texture); + return cogl_multi_plane_texture_get_width (surface->texture); else return 0; } @@ -257,7 +257,7 @@ get_buffer_height (MetaWaylandSurface *surface) MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); if (buffer) - return cogl_texture_get_height (surface->texture); + return cogl_multi_plane_texture_get_height (surface->texture); else return 0; } @@ -721,7 +721,7 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface, if (changed_texture && meta_wayland_surface_get_actor (surface)) { MetaShapedTexture *stex; - CoglTexture *texture; + CoglMultiPlaneTexture *texture; CoglSnippet *snippet; gboolean is_y_inverted; @@ -1846,7 +1846,7 @@ meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface, return g_hash_table_contains (surface->shortcut_inhibited_seats, seat); } -CoglTexture * +CoglMultiPlaneTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface) { return surface->texture; diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index e244a3fdf..b82cdc600 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -149,7 +149,7 @@ struct _MetaWaylandSurface GHashTable *outputs_to_destroy_notify_id; MetaMonitorTransform buffer_transform; - CoglTexture *texture; + CoglMultiPlaneTexture *texture; /* Buffer reference state. */ struct { @@ -319,7 +319,7 @@ void meta_wayland_surface_restore_shortcuts (MetaWaylandSurface * gboolean meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface, MetaWaylandSeat *seat); -CoglTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface); +CoglMultiPlaneTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface); MetaSurfaceActor * meta_wayland_surface_get_actor (MetaWaylandSurface *surface); diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index dee5cdd59..62bb59a14 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -306,6 +306,26 @@ meta_wayland_log_func (const char *fmt, } static void +add_supported_shm_formats (struct wl_display *display) +{ + guint i; + + /* Note that a Wayland compositor should support WL_SHM_FORMAT_ARGB8888 and + * WL_SHM_FORMAT_XRGB8888 by default, so no need to add it here. */ + static const guint32 SUPPORTED_FORMATS[] = { + WL_SHM_FORMAT_NV12, + WL_SHM_FORMAT_NV21, + WL_SHM_FORMAT_YUV422, + WL_SHM_FORMAT_YUV444, + }; + + for (i = 0; i < G_N_ELEMENTS (SUPPORTED_FORMATS); i++) + { + wl_display_add_shm_format (display, SUPPORTED_FORMATS[i]); + } +} + +static void meta_wayland_compositor_init (MetaWaylandCompositor *compositor) { wl_list_init (&compositor->frame_callbacks); @@ -317,6 +337,8 @@ meta_wayland_compositor_init (MetaWaylandCompositor *compositor) compositor->wayland_display = wl_display_create (); if (compositor->wayland_display == NULL) g_error ("Failed to create the global wl_display"); + + add_supported_shm_formats (compositor->wayland_display); } static void |