[mutter/wip/nielsdg/add-yuv-support: 48/48] WIP
- From: Niels De Graef <nielsdg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/nielsdg/add-yuv-support: 48/48] WIP
- Date: Tue, 20 Nov 2018 14:27:21 +0000 (UTC)
commit 5abfd46063f1d0620fc09cfd9ff64ea21daf2fec
Author: Niels De Graef <Niels DeGraef barco com>
Date: Tue Nov 20 15:24:31 2018 +0100
WIP
cogl/cogl/driver/gl/gl/cogl-driver-gl.c | 5 ++
src/compositor/meta-planar-texture.c | 25 ++++++
src/compositor/meta-planar-texture.h | 11 ++-
src/compositor/meta-shaped-texture.c | 4 -
src/wayland/meta-wayland-buffer.c | 141 +++++++++++++++++++++++---------
src/wayland/meta-wayland-dma-buf.c | 5 +-
src/wayland/meta-wayland.c | 19 +++++
7 files changed, 159 insertions(+), 51 deletions(-)
---
diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
index d627dddf7..5181bbe22 100644
--- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
+++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
@@ -280,6 +280,11 @@ _cogl_driver_pixel_format_to_gl_with_target (CoglContext *context,
gltype = GL_UNSIGNED_INT_24_8;
break;
+ case COGL_PIXEL_FORMAT_Y_UV:
+ glintformat = GL_RGBA;
+ glformat = GL_RGBA;
+ break;
+
case COGL_PIXEL_FORMAT_ANY:
case COGL_PIXEL_FORMAT_YUV:
g_assert_not_reached ();
diff --git a/src/compositor/meta-planar-texture.c b/src/compositor/meta-planar-texture.c
index 36f0214cc..76d2c52c1 100644
--- a/src/compositor/meta-planar-texture.c
+++ b/src/compositor/meta-planar-texture.c
@@ -147,3 +147,28 @@ _cogl_pixel_format_get_n_planes (CoglPixelFormat format)
g_assert_not_reached ();
}
+
+/**
+ * _cogl_pixel_format_get_subsampling_parameters:
+ *
+ * Returns the subsampling in both the horizontal as the vertical direction.
+ */
+void
+_cogl_pixel_format_get_subsampling_parameters (CoglPixelFormat format,
+ guint *horizontal_params,
+ guint *vertical_params)
+{
+ switch (format)
+ {
+ case COGL_PIXEL_FORMAT_Y_UV:
+ horizontal_params[0] = 1;
+ vertical_params[0] = 1;
+ horizontal_params[1] = 2;
+ vertical_params[1] = 2;
+ break;
+ default:
+ horizontal_params[0] = 1;
+ vertical_params[0] = 1;
+ break;
+ }
+}
diff --git a/src/compositor/meta-planar-texture.h b/src/compositor/meta-planar-texture.h
index 616be2781..3a1b507c7 100644
--- a/src/compositor/meta-planar-texture.h
+++ b/src/compositor/meta-planar-texture.h
@@ -51,15 +51,14 @@ guint meta_planar_texture_get_width (MetaPlanarTexture *self);
guint meta_planar_texture_get_height (MetaPlanarTexture *self);
-/**
- * _cogl_pixel_format_get_n_planes:
- * @format: a #CoglPixelFormat
- *
- * Returns the number of planes the given CoglPixelFormat specifies.
- */
guint
_cogl_pixel_format_get_n_planes (CoglPixelFormat format);
+void
+_cogl_pixel_format_get_subsampling_parameters (CoglPixelFormat format,
+ guint *horizontal_params,
+ guint *vertical_params);
+
G_END_DECLS
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index fb1b7a4af..015f17104 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -387,13 +387,9 @@ check_texture_color_format (MetaShapedTexture *self,
" float v = uv.y;\n"
" color.r = y + 1.59765625 * v;\n"
- /* " color.r = 0.0;\n" */
" color.g = y - 0.390625 * u - 0.8125 * v;\n"
- /* " color.g = 0.0;\n" */
" color.b = y + 2.015625 * u;\n"
- /* " color.b = 0.0;\n" */
" color.a = 1.0;\n"
- /* " color = vec4 (y, u, u, 1.0);\n" */
" return color;\n"
"}\n";
diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c
index d3f08125c..ad1725341 100644
--- a/src/wayland/meta-wayland-buffer.c
+++ b/src/wayland/meta-wayland-buffer.c
@@ -160,11 +160,14 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
static void
shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
CoglPixelFormat *format_out,
- CoglTextureComponents *components_out)
+ CoglTextureComponents *components_out,
+ guint *n_planes_out)
{
CoglPixelFormat format;
CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA;
+ guint n_planes = 1;
+ g_warning ("SHM BUFFER_FORMAT: %d", wl_shm_buffer_get_format (shm_buffer));
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
@@ -185,17 +188,25 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
break;
#endif
case WL_SHM_FORMAT_NV12:
+ format = COGL_PIXEL_FORMAT_Y_UV;
+ n_planes = 2;
g_warning ("FORMAT IS NV12");
+ break;
case WL_SHM_FORMAT_NV21:
g_warning ("FORMAT IS NV21");
+ break;
case WL_SHM_FORMAT_YUV422:
g_warning ("FORMAT IS YUV422");
+ break;
case WL_SHM_FORMAT_YVU422:
g_warning ("FORMAT IS YVU422");
+ break;
case WL_SHM_FORMAT_YUV444:
g_warning ("FORMAT IS YUV444");
+ break;
case WL_SHM_FORMAT_YVU444:
g_warning ("FORMAT IS YVU444");
+ break;
default:
g_warn_if_reached ();
@@ -206,6 +217,8 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
*format_out = format;
if (components_out)
*components_out = components;
+ if (n_planes_out)
+ *n_planes_out = n_planes;
}
static gboolean
@@ -219,44 +232,81 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
int stride, width, height;
CoglPixelFormat format;
CoglTextureComponents components;
- CoglBitmap *bitmap;
- CoglTexture *texture;
+ guint i, n_planes;
+ guint h_subsampling[3], v_subsampling[3];
+ gsize offset = 0;
+ const guint8 *data;
+ GPtrArray *planes;
+ gboolean ret;
if (buffer->texture)
return TRUE;
+ /* 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);
- wl_shm_buffer_begin_access (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_subsampling_parameters (format,
+ h_subsampling,
+ v_subsampling);
- bitmap = cogl_bitmap_new_for_data (cogl_context,
- width, height,
- format,
- stride,
- wl_shm_buffer_get_data (shm_buffer));
+ /* Safely access the data inside the buffer */
+ wl_shm_buffer_begin_access (shm_buffer);
+ data = wl_shm_buffer_get_data (shm_buffer);
- texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap));
- cogl_texture_set_components (COGL_TEXTURE (texture), components);
+ planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
+ for (i = 0; i < n_planes; i++)
+ {
+ CoglBitmap *bitmap;
+ CoglTexture *plane;
+
+ /* Internally, the texture's planes are laid out in memory as one
+ * contiguous block, so we have to consider any subsampling (based on the
+ * pixel format). */
+ if (i == 0)
+ offset = 0;
+ else
+ offset += (stride / h_subsampling[i-1]) * (height / v_subsampling[i-1]);
+
+ bitmap = cogl_bitmap_new_for_data (cogl_context,
+ width / h_subsampling[i],
+ height / v_subsampling[i],
+ format,
+ stride, /* XXX Do we need to change this too?*/
+ data + offset);
+ g_assert (bitmap);
+
+ plane = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap));
+ cogl_texture_set_components (COGL_TEXTURE (plane), components);
+
+ cogl_object_unref (bitmap);
+
+ if (G_UNLIKELY (!cogl_texture_allocate (COGL_TEXTURE (plane), error)))
+ {
+ g_clear_pointer (&plane, cogl_object_unref);
+ ret = FALSE;
+ goto out;
+ }
- cogl_object_unref (bitmap);
+ g_ptr_array_add (planes, plane);
+ }
- if (!cogl_texture_allocate (COGL_TEXTURE (texture), error))
- g_clear_pointer (&texture, cogl_object_unref);
+ buffer->texture = meta_planar_texture_new (format,
+ g_ptr_array_free (planes, FALSE),
+ n_planes);
+ buffer->is_y_inverted = TRUE;
+ ret = TRUE;
+out:
wl_shm_buffer_end_access (shm_buffer);
- buffer->texture = texture;
- buffer->is_y_inverted = TRUE;
-
- if (!buffer->texture)
- return FALSE;
+ if (!ret)
+ g_ptr_array_free (planes, TRUE);
- return TRUE;
+ return ret;
}
static gboolean
@@ -271,7 +321,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
int format, width, height, y_inverted;
CoglPixelFormat cogl_format;
guint i, n_planes;
- GPtrArray *textures;
+ GPtrArray *planes;
gboolean ret = FALSE;
EGLint attrib_list[3] = { EGL_NONE, EGL_NONE, EGL_NONE };
@@ -320,7 +370,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
}
n_planes = _cogl_pixel_format_get_n_planes (cogl_format);
- textures = g_ptr_array_new_full (n_planes, cogl_object_unref);
+ planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
/* Each EGLImage is a plane in the final texture */
for (i = 0; i < n_planes; i++)
@@ -339,7 +389,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
attrib_list,
error);
- if (egl_img == EGL_NO_IMAGE_KHR)
+ if (G_UNLIKELY (egl_img == EGL_NO_IMAGE_KHR))
goto out;
texture = cogl_egl_texture_2d_new_from_image (cogl_context,
@@ -350,15 +400,15 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
meta_egl_destroy_image (egl, egl_display, egl_img, NULL);
- if (!texture)
+ if (G_UNLIKELY (!texture))
goto out;
- g_ptr_array_add (textures, texture);
+ g_ptr_array_add (planes, texture);
}
buffer->texture = meta_planar_texture_new (cogl_format,
- g_ptr_array_free (textures, FALSE),
+ g_ptr_array_free (planes, FALSE),
n_planes);
buffer->is_y_inverted = !!y_inverted;
@@ -366,7 +416,7 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
out:
if (!ret)
- g_ptr_array_free (textures, TRUE);
+ g_ptr_array_free (planes, TRUE);
return ret;
}
@@ -405,14 +455,18 @@ meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
switch (buffer->type)
{
case META_WAYLAND_BUFFER_TYPE_SHM:
+ g_warning ("GOT SHM BUFFER");
return shm_buffer_attach (buffer, error);
case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE:
+ g_warning ("GOT EGL IMAGE BUFFER");
return egl_image_buffer_attach (buffer, error);
#ifdef HAVE_WAYLAND_EGLSTREAM
case META_WAYLAND_BUFFER_TYPE_EGL_STREAM:
+ g_warning ("GOT EGL STREAM BUFFER");
return egl_stream_buffer_attach (buffer, error);
#endif
case META_WAYLAND_BUFFER_TYPE_DMA_BUF:
+ g_warning ("GOT DMA BUF BUFFER");
return meta_wayland_dma_buf_buffer_attach (buffer, error);
case META_WAYLAND_BUFFER_TYPE_UNKNOWN:
g_assert_not_reached ();
@@ -466,27 +520,34 @@ process_shm_buffer_damage (MetaWaylandBuffer *buffer,
const uint8_t *data = wl_shm_buffer_get_data (shm_buffer);
int32_t stride = wl_shm_buffer_get_stride (shm_buffer);
CoglPixelFormat format;
+ guint n_planes;
int bpp;
cairo_rectangle_int_t rect;
- shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL);
+ shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL, &n_planes);
bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
cairo_region_get_rectangle (region, i, &rect);
- if (!_cogl_texture_set_region (buffer->texture,
- rect.width, rect.height,
- format,
- stride,
- data + rect.x * bpp + rect.y * stride,
- rect.x, rect.y,
- 0,
- error))
+ for (i = 0; i < n_planes; i++)
{
- set_texture_failed = TRUE;
- break;
+ CoglTexture *plane = meta_planar_texture_get_plane (buffer->texture, i);
+
+ if (!_cogl_texture_set_region (plane,
+ rect.width, rect.height,
+ format,
+ stride,
+ data + rect.x * bpp + rect.y * stride,
+ rect.x, rect.y,
+ 0,
+ error))
+ {
+ set_texture_failed = TRUE;
+ goto out;
+ }
}
}
+out:
wl_shm_buffer_end_access (shm_buffer);
return !set_texture_failed;
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 347da2484..1abdc934e 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -78,6 +78,7 @@ meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
CoglPixelFormat cogl_format;
EGLImageKHR egl_image;
CoglTexture2D *texture;
+ CoglTexture **textures;
EGLint attribs[64];
int attr_idx = 0;
@@ -196,7 +197,9 @@ meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
if (!texture)
return FALSE;
- buffer->texture = COGL_TEXTURE (texture);
+ textures = g_new (CoglTexture *, 1);
+ textures[0] = COGL_TEXTURE (texture);
+ buffer->texture = meta_planar_texture_new (cogl_format, textures, 1);
buffer->is_y_inverted = dma_buf->is_y_inverted;
return TRUE;
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 25b49918f..d2436d6b6 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -311,6 +311,23 @@ meta_wayland_compositor_init (MetaWaylandCompositor *compositor)
compositor->scheduled_surface_associations = g_hash_table_new (NULL, NULL);
}
+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
+ };
+
+ for (i = 0; i < G_N_ELEMENTS (SUPPORTED_FORMATS); i++)
+ {
+ wl_display_add_shm_format (display, SUPPORTED_FORMATS[i]);
+ }
+}
+
void
meta_wayland_pre_clutter_init (void)
{
@@ -325,6 +342,8 @@ meta_wayland_pre_clutter_init (void)
g_error ("Failed to create the global wl_display");
clutter_wayland_set_compositor_display (compositor->wayland_display);
+
+ add_supported_shm_formats (compositor->wayland_display);
}
static bool
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]