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



commit dbf179fa7da8d484231ea6213c023a9ec672e51b
Author: Niels De Graef <niels degraef barco com>
Date:   Sat Jun 15 06:35:52 2019 +0200

    WIP

 cogl/cogl/cogl-multi-plane-texture.c            |  52 ------------
 cogl/cogl/cogl-multi-plane-texture.h            |  18 ----
 cogl/cogl/cogl-pixel-format-conversion.c        |  47 ++++++++---
 cogl/cogl/driver/gl/cogl-texture-2d-gl.c        |   4 -
 cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c |   2 -
 src/compositor/meta-shaped-texture.c            |   2 -
 src/wayland/meta-wayland-buffer.c               | 108 +++++++++++++++++-------
 src/wayland/meta-wayland-dma-buf.c              |   9 +-
 8 files changed, 112 insertions(+), 130 deletions(-)
---
diff --git a/cogl/cogl/cogl-multi-plane-texture.c b/cogl/cogl/cogl-multi-plane-texture.c
index e9cb916ab..209291579 100644
--- a/cogl/cogl/cogl-multi-plane-texture.c
+++ b/cogl/cogl/cogl-multi-plane-texture.c
@@ -127,58 +127,6 @@ cogl_multi_plane_texture_new_single_plane (CoglPixelFormat format,
   return self;
 }
 
-CoglMultiPlaneTexture *
-cogl_multi_plane_texture_new_from_bitmaps (CoglPixelFormat format,
-                                           CoglBitmap **bitmaps, guint n_planes,
-                                           GError **error)
-{
-  guint i = 0;
-  CoglMultiPlaneTexture *self = g_slice_new0 (CoglMultiPlaneTexture);
-
-  _cogl_multi_plane_texture_object_new (self);
-
-  self->format = format;
-  self->n_planes = n_planes;
-  self->planes = g_malloc (sizeof (CoglTexture *) * n_planes);
-
-  for (i = 0; i < n_planes; i++)
-    {
-      CoglTexture *plane;
-
-      plane = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmaps[i]));
-
-      if (!cogl_texture_allocate (plane, error))
-        {
-          g_clear_pointer (&plane, cogl_object_unref);
-
-          /* There's a chance we failed due to the buffer being NPOT size.
-           * If so, try again with CoglTexture2DSliced (which does support this) */
-          if (g_error_matches (*error,
-                               COGL_TEXTURE_ERROR,
-                               COGL_TEXTURE_ERROR_SIZE))
-            {
-              CoglTexture2DSliced *plane_sliced;
-
-              g_clear_error (error);
-
-              plane_sliced =
-                cogl_texture_2d_sliced_new_from_bitmap (bitmaps[i],
-                                                        COGL_TEXTURE_MAX_WASTE);
-              plane = COGL_TEXTURE (plane_sliced);
-
-              if (!cogl_texture_allocate (plane, error))
-                cogl_clear_object (&plane);
-            }
-        }
-
-      cogl_object_unref (bitmaps[i]);
-      self->planes[i] = plane;
-    }
-
-
-  return self;
-}
-
 gchar *
 cogl_multi_plane_texture_to_string (CoglMultiPlaneTexture *self)
 {
diff --git a/cogl/cogl/cogl-multi-plane-texture.h b/cogl/cogl/cogl-multi-plane-texture.h
index c0d8d89b9..5a46cfa74 100644
--- a/cogl/cogl/cogl-multi-plane-texture.h
+++ b/cogl/cogl/cogl-multi-plane-texture.h
@@ -100,24 +100,6 @@ CoglMultiPlaneTexture * cogl_multi_plane_texture_new  (CoglPixelFormat format,
 CoglMultiPlaneTexture * cogl_multi_plane_texture_new_single_plane (CoglPixelFormat format,
                                                                    CoglTexture *plane);
 
-/**
- * cogl_multi_plane_texture_new_from_bitmaps:
- * @format: The format of the new #CoglMultiPlaneTexture
- * @bitmaps: (transfer full): The planes of the texture, each as a #CoglBitmap
- * @n_planes: the number of planes the texture contains
- * @error: (out): Will be set if an error occurred
- *
- * Creates a #CoglMultiPlaneTexture from the given bitmaps and makes sure the
- * planes are uploaded to the GPU.
- *
- * Returns: (transfer full): A new #CoglMultiPlaneTexture. Use
- * cogl_object_unref() when you're done with it.
- */
-CoglMultiPlaneTexture *
-cogl_multi_plane_texture_new_from_bitmaps (CoglPixelFormat format,
-                                           CoglBitmap **bitmaps, guint n_planes,
-                                           GError **error);
-
 /**
  * cogl_multi_plane_texture_get_format:
  * @self: a #CoglMultiPlaneTexture
diff --git a/cogl/cogl/cogl-pixel-format-conversion.c b/cogl/cogl/cogl-pixel-format-conversion.c
index 6b505705e..e0d926e1a 100644
--- a/cogl/cogl/cogl-pixel-format-conversion.c
+++ b/cogl/cogl/cogl-pixel-format-conversion.c
@@ -26,17 +26,31 @@
 #include "cogl-pipeline-layer-state.h"
 #include "cogl-pipeline-state.h"
 
-#define _COGL_YUV_TO_RGBA(res, y, u, v)                     \
-    res ".r = " y " + 1.59765625 * " v ";\n"                \
-    res ".g = " y " - 0.390625 * " u " - 0.8125 * " v ";\n" \
-    res ".b = " y " + 2.015625 * " u ";\n"                  \
+#define _COGL_YUV_TO_RGBA(res, y, u, v)                           \
+    "vec4 " res ";\n"                                             \
+    res ".r = (" y ") + 1.59765625 * (" v ");\n"                  \
+    res ".g = (" y ") - 0.390625 * (" u ") - 0.8125 * (" v ");\n" \
+    res ".b = (" y ") + 2.015625 * (" u ");\n"                    \
     res ".a = 1.0;\n"
 
-static const gchar nv12_to_rgba_shader[] =
+/* Shader for a single YUV plane */
+static const gchar yuv_to_rgba_shader[] =
     "vec4\n"
-    "cogl_nv12_to_rgba (vec2 UV)\n"
+    "cogl_yuv_to_rgba (vec2 UV)\n"
+    "{\n"
+    "  vec4 orig_color = texture2D(cogl_sampler0, UV);\n"
+    "  float y = 1.16438356 * (orig_color.r - 0.0625);\n"
+    "  float u = orig_color.g - 0.5;\n"
+    "  float v = orig_color.b - 0.5;\n"
+       _COGL_YUV_TO_RGBA ("color", "y", "u", "v")
+    "  return color;\n"
+    "}\n";
+
+/* Shader for 1 Y-plane and 1 UV-plane */
+static const gchar y_uv_to_rgba_shader[] =
+    "vec4\n"
+    "cogl_y_uv_to_rgba (vec2 UV)\n"
     "{\n"
-    "  vec4 color;\n"
     "  float y = 1.1640625 * (texture2D (cogl_sampler0, UV).x - 0.0625);\n"
     "  vec2 uv = texture2D (cogl_sampler1, UV).rg;\n"
     "  uv -= 0.5;\n"
@@ -46,11 +60,11 @@ static const gchar nv12_to_rgba_shader[] =
     "  return color;\n"
     "}\n";
 
-static const gchar yuv_to_rgba_shader[] =
+/* Shader for 1 Y-plane, 1 U-plane and 1 V-plane */
+static const gchar y_u_v_to_rgba_shader[] =
     "vec4\n"
-    "cogl_yuv_to_rgba (vec2 UV)\n"
+    "cogl_y_u_v_to_rgba (vec2 UV)\n"
     "{\n"
-    "  vec4 color;\n"
     "  float y = 1.16438356 * (texture2D(cogl_sampler0, UV).x - 0.0625);\n"
     "  float u = texture2D(cogl_sampler1, UV).x - 0.5;\n"
     "  float v = texture2D(cogl_sampler2, UV).x - 0.5;\n"
@@ -99,14 +113,19 @@ get_cogl_snippets (CoglPixelFormat format,
 
   switch (format)
     {
-    case COGL_PIXEL_FORMAT_YUV444:
+    case COGL_PIXEL_FORMAT_AYUV:
       global_hook = yuv_to_rgba_shader;
-      layer_hook =  "cogl_layer = cogl_yuv_to_rgba(cogl_tex_coord0_in.st);\n";
+      layer_hook = "cogl_layer = cogl_yuv_to_rgba(cogl_tex_coord0_in.st);\n";
       break;
     case COGL_PIXEL_FORMAT_NV12:
       /* XXX are we using Y_UV or Y_xUxV? Maybe check for RG support? */
-      global_hook = nv12_to_rgba_shader;
-      layer_hook =  "cogl_layer = cogl_nv12_to_rgba(cogl_tex_coord0_in.st);\n";
+      global_hook = y_uv_to_rgba_shader;
+      layer_hook = "cogl_layer = cogl_y_uv_to_rgba(cogl_tex_coord0_in.st);\n";
+      break;
+    case COGL_PIXEL_FORMAT_YUV444:
+    case COGL_PIXEL_FORMAT_YUV422:
+      global_hook = y_u_v_to_rgba_shader;
+      layer_hook = "cogl_layer = cogl_y_u_v_to_rgba(cogl_tex_coord0_in.st);\n";
       break;
     default:
       *vertex_snippet_out = NULL;
diff --git a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
index fe4a53dfc..2f9e3424c 100644
--- a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
+++ b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
@@ -202,8 +202,6 @@ allocate_from_bitmap (CoglTexture2D *tex_2d,
   GLenum gl_format;
   GLenum gl_type;
 
-  g_warning ("allocate_from_bitmap()");
-
   internal_format =
     _cogl_texture_determine_internal_format (tex, cogl_bitmap_get_format (bmp));
 
@@ -344,8 +342,6 @@ allocate_from_gl_foreign (CoglTexture2D *tex_2d,
   GLint gl_compressed = GL_FALSE;
   GLenum gl_int_format = 0;
 
-  g_warning ("allocate_from_egl_image_foreign()");
-
   if (!ctx->texture_driver->allows_foreign_gl_target (ctx, GL_TEXTURE_2D))
     {
       _cogl_set_error (error,
diff --git a/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c
index 84d87138c..f5e9a4732 100644
--- a/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c
+++ b/cogl/cogl/driver/gl/gl/cogl-texture-driver-gl.c
@@ -98,8 +98,6 @@ _cogl_texture_driver_gen (CoglContext *ctx,
       g_assert_not_reached();
     }
 
-  g_warning ("_cogl_texture_driver_gen %s", cogl_pixel_format_to_string (internal_format));
-
   /* If the driver doesn't support alpha textures directly then we'll
    * fake them by setting the swizzle parameters */
   if (internal_format == COGL_PIXEL_FORMAT_A_8 &&
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index c6dfa76e7..c8a8f46e0 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -279,8 +279,6 @@ set_clip_region (MetaShapedTexture *stex,
 static void
 meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
 {
-  g_warning ("resetting pipelines!");
-
   cogl_clear_object (&stex->pixel_format_conversion);
 
   cogl_clear_object (&stex->base_pipeline);
diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c
index 3de148f7a..969d9b26d 100644
--- a/src/wayland/meta-wayland-buffer.c
+++ b/src/wayland/meta-wayland-buffer.c
@@ -178,6 +178,7 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer  *shm_buffer,
 #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;
@@ -243,11 +244,11 @@ shm_buffer_attach (MetaWaylandBuffer      *buffer,
   CoglPixelFormat format;
   CoglTextureComponents components[3];
   guint i, n_planes;
-  uint8_t h_factors[3], v_factors[3];
+  uint8_t h_factors[3], v_factors[3], bpp[3];
   CoglPixelFormat subformats[3];
   gsize plane_offset = 0;
   guint8 *data;
-  GPtrArray *bitmaps;
+  GPtrArray *planes;
 
   /* Query the necessary parameters */
   shm_buffer = wl_shm_buffer_get (buffer->resource);
@@ -258,8 +259,7 @@ shm_buffer_attach (MetaWaylandBuffer      *buffer,
   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);
-
-  g_warning ("Got SHM buffer, format %s", cogl_pixel_format_to_string (format));
+  cogl_pixel_format_get_bytes_per_pixel_ (format, bpp);
 
   if (*texture &&
       cogl_multi_plane_texture_get_width (*texture) == width &&
@@ -278,41 +278,81 @@ shm_buffer_attach (MetaWaylandBuffer      *buffer,
   wl_shm_buffer_begin_access (shm_buffer);
   data = wl_shm_buffer_get_data (shm_buffer);
 
-  bitmaps = g_ptr_array_new_full (n_planes, cogl_object_unref);
+  planes = g_ptr_array_new_full (n_planes, cogl_object_unref);
   for (i = 0; i < n_planes; i++)
     {
-      CoglBitmap *bitmap;
+      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;
+            }
 
-      /* Calculate the plane start in the buffer (consider subsampling) */
-      if (i > 0)
-        plane_offset += (stride / h_factors[i-1]) * (height / v_factors[i-1]);
+          g_clear_error (error);
 
-      g_warning ("Creating plane %u, h_factor = %u, v_factor = %u, plane_offset = %lu",
-                 i, h_factors[i], v_factors[i], plane_offset);
+          texture_sliced =
+            cogl_texture_2d_sliced_new_from_bitmap (plane_bitmap,
+                                                    COGL_TEXTURE_MAX_WASTE);
+          plane_texture = COGL_TEXTURE (texture_sliced);
 
-      bitmap = cogl_bitmap_new_for_data (cogl_context,
-                                         width / h_factors[i],
-                                         height / v_factors[i],
-                                         subformats[i],
-                                         stride / h_factors[i],
-                                         data + plane_offset);
-      g_assert (bitmap);
+          cogl_texture_set_components (plane_texture, components[i]);
 
-      g_ptr_array_add (bitmaps, bitmap);
+          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]);
     }
 
-  *texture = cogl_multi_plane_texture_new_from_bitmaps (format,
-                                          (CoglBitmap **) g_ptr_array_free (bitmaps, FALSE),
-                                          n_planes, error);
+  *texture = cogl_multi_plane_texture_new (format,
+                                          (CoglTexture **) g_ptr_array_free (planes, FALSE),
+                                          n_planes);
 
   wl_shm_buffer_end_access (shm_buffer);
 
   *changed_texture = TRUE;
   buffer->is_y_inverted = TRUE;
 
-  g_warning ("Got the following multiplane texture:\n%s", cogl_multi_plane_texture_to_string (*texture));
-
   return TRUE;
+
+failure:
+  *texture = NULL;
+  return FALSE;
 }
 
 static gboolean
@@ -578,6 +618,8 @@ process_shm_buffer_damage (MetaWaylandBuffer      *buffer,
   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);
+
+  /* Fetch some properties from the pixel format */
   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);
@@ -587,16 +629,15 @@ process_shm_buffer_damage (MetaWaylandBuffer      *buffer,
   for (i = 0; i < n_planes; i++)
     {
       CoglTexture *plane;
+      int plane_stride;
 
       plane = cogl_multi_plane_texture_get_plane (texture, i);
-
-      /* Calculate the plane start in the buffer (consider subsampling) */
-      if (i > 0)
-        plane_offset += (stride / h_factors[i-1]) * (height / v_factors[i-1]);
+      plane_stride = (stride / bpp[0]) * bpp[i] / h_factors[i];
 
       for (j = 0; j < n_rectangles; j++)
         {
           cairo_rectangle_int_t rect;
+          gsize rect_offset;
 
           cairo_region_get_rectangle (region, j, &rect);
 
@@ -604,12 +645,16 @@ process_shm_buffer_damage (MetaWaylandBuffer      *buffer,
           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],
-                                         stride,
-                                         data + plane_offset + rect.x * bpp[i] + rect.y * stride,
+                                         plane_stride,
+                                         data + rect_offset,
                                          rect.x, rect.y,
                                          0,
                                          error))
@@ -618,6 +663,9 @@ process_shm_buffer_damage (MetaWaylandBuffer      *buffer,
               goto out;
             }
         }
+
+      /* Calculate the next plane start in the buffer (consider subsampling) */
+      plane_offset += plane_stride * (height / v_factors[i]);
     }
 
 out:
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 839fa1e4d..fea412b2d 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -625,16 +625,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_YUV410);
-  send_modifiers (resource, DRM_FORMAT_YVU410);
-  send_modifiers (resource, DRM_FORMAT_YUV411);
-  send_modifiers (resource, DRM_FORMAT_YVU420);
-  send_modifiers (resource, DRM_FORMAT_YVU420);
   send_modifiers (resource, DRM_FORMAT_YUV422);
-  send_modifiers (resource, DRM_FORMAT_YVU422);
-  send_modifiers (resource, DRM_FORMAT_YUV444);
-  send_modifiers (resource, DRM_FORMAT_YVU444);
 }
 
 gboolean


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