[mutter/wip/nielsdg/add-yuv-support: 48/48] WIP



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]