[Cogl] [PATCH] wayland: Add a convenience function to update a region from SHM buffer

Neil Roberts neil at linux.intel.com
Mon Nov 25 09:04:16 PST 2013


Here is a proposed replacement for the following patch which was
pushed onto the 1.18 branch without first going through the master
branch. If we go with this patch then we can revert the patch on the
1.18 branch and cherry-pick this one from master.

https://git.gnome.org/browse/cogl/commit/?id=af480a2b8b5450148ca4b9

The changes from that patch are that it is no longer specific to
CoglTexture2D and its arguments more closely match those from
cogl_texture_set_region on the master branch. This includes a
parameter for the mipmap level and separate arguments for the src and
dst offsets. It also includes a patch to cogland to take advantage of
the function.

------- >8 --------------- (use git am --scissors to automatically chop here)

Adds cogl_wayland_texture_set_region_from_shm_buffer which is a
convenience wrapper around cogl_texture_set_region but it uses the
correct format to copy the data from a Wayland SHM buffer. This will
typically be used by compositors to update the texture for a surface
when an SHM buffer is attached. The ordering of the arguments is based
on cogl_texture_set_region_from_bitmap.

Based on a patch by Jasper St. Pierre.
---
 cogl/cogl-texture-2d.c     | 96 ++++++++++++++++++++++++++++++++++------------
 cogl/cogl-wayland-server.h | 44 +++++++++++++++++++++
 examples/cogland.c         | 44 +++++----------------
 3 files changed, 125 insertions(+), 59 deletions(-)

diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c
index 07a9a3c..5023378 100644
--- a/cogl/cogl-texture-2d.c
+++ b/cogl/cogl-texture-2d.c
@@ -292,6 +292,75 @@ _cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
 #endif /* defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) */
 
 #ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT
+static void
+shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
+                                  CoglPixelFormat *format_out,
+                                  CoglPixelFormat *internal_format_out)
+{
+  CoglPixelFormat format;
+  CoglPixelFormat internal_format = COGL_PIXEL_FORMAT_ANY;
+
+  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;
+      break;
+    case WL_SHM_FORMAT_XRGB8888:
+      format = COGL_PIXEL_FORMAT_ARGB_8888;
+      internal_format = COGL_PIXEL_FORMAT_RGB_888;
+      break;
+#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
+    case WL_SHM_FORMAT_ARGB8888:
+      format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
+      break;
+    case WL_SHM_FORMAT_XRGB8888:
+      format = COGL_PIXEL_FORMAT_BGRA_8888;
+      internal_format = COGL_PIXEL_FORMAT_BGR_888;
+      break;
+#endif
+    default:
+      g_warn_if_reached ();
+      format = COGL_PIXEL_FORMAT_ARGB_8888;
+    }
+
+  if (format_out)
+    *format_out = format;
+  if (internal_format_out)
+    *internal_format_out = internal_format;
+}
+
+CoglBool
+cogl_wayland_texture_set_region_from_shm_buffer (CoglTexture *texture,
+                                                 int src_x,
+                                                 int src_y,
+                                                 int width,
+                                                 int height,
+                                                 struct wl_shm_buffer *
+                                                   shm_buffer,
+                                                 int dst_x,
+                                                 int dst_y,
+                                                 int level,
+                                                 CoglError **error)
+{
+  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;
+
+  shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL);
+  bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
+
+  return cogl_texture_set_region (COGL_TEXTURE (texture),
+                                  width, height,
+                                  format,
+                                  stride,
+                                  data + src_x * bpp + src_y * stride,
+                                  dst_x, dst_y,
+                                  level,
+                                  error);
+}
+
 CoglTexture2D *
 cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx,
                                          struct wl_resource *buffer,
@@ -304,34 +373,11 @@ cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx,
   if (shm_buffer)
     {
       int stride = wl_shm_buffer_get_stride (shm_buffer);
-      CoglPixelFormat format;
-      CoglPixelFormat internal_format = COGL_PIXEL_FORMAT_ANY;
       int width = wl_shm_buffer_get_width (shm_buffer);
       int height = wl_shm_buffer_get_height (shm_buffer);
+      CoglPixelFormat format, internal_format;
 
-      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;
-            break;
-          case WL_SHM_FORMAT_XRGB8888:
-            format = COGL_PIXEL_FORMAT_ARGB_8888;
-            internal_format = COGL_PIXEL_FORMAT_RGB_888;
-            break;
-#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
-          case WL_SHM_FORMAT_ARGB8888:
-            format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
-            break;
-          case WL_SHM_FORMAT_XRGB8888:
-            format = COGL_PIXEL_FORMAT_BGRA_8888;
-            internal_format = COGL_PIXEL_FORMAT_BGR_888;
-            break;
-#endif
-          default:
-            g_warn_if_reached ();
-            format = COGL_PIXEL_FORMAT_ARGB_8888;
-        }
+      shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &internal_format);
 
       return cogl_texture_2d_new_from_data (ctx,
                                             width, height,
diff --git a/cogl/cogl-wayland-server.h b/cogl/cogl-wayland-server.h
index e56f5bd..9eded9b 100644
--- a/cogl/cogl-wayland-server.h
+++ b/cogl/cogl-wayland-server.h
@@ -79,6 +79,50 @@ cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx,
                                          struct wl_resource *buffer,
                                          CoglError **error);
 
+/**
+ * cogl_wayland_texture_set_region_from_shm_buffer:
+ * @texture: a #CoglTexture
+ * @width: The width of the region to copy
+ * @height: The height of the region to copy
+ * @shm_buffer: The source buffer
+ * @src_x: The X offset within the source bufer to copy from
+ * @src_y: The Y offset within the source bufer to copy from
+ * @dst_x: The X offset within the texture to copy to
+ * @dst_y: The Y offset within the texture to copy to
+ * @level: The mipmap level of the texture to copy to
+ * @error: A #CoglError to return exceptional errors
+ *
+ * Sets the pixels in a rectangular subregion of @texture from a
+ * Wayland SHM buffer. Generally this would be used in response to
+ * wl_surface.damage event in a compositor in order to update the
+ * texture with the damaged region. This is just a convenience wrapper
+ * around getting the SHM buffer pointer and calling
+ * cogl_texture_set_region(). See that function for a description of
+ * the level parameter.
+ *
+ * <note>Since the storage for a #CoglTexture is allocated lazily then
+ * if the given @texture has not previously been allocated then this
+ * api can return %FALSE and throw an exceptional @error if there is
+ * not enough memory to allocate storage for @texture.</note>
+ *
+ * Return value: %TRUE if the subregion upload was successful, and
+ *   %FALSE otherwise
+ * Since: 1.18
+ * Stability: unstable
+ */
+CoglBool
+cogl_wayland_texture_set_region_from_shm_buffer (CoglTexture *texture,
+                                                 int src_x,
+                                                 int src_y,
+                                                 int width,
+                                                 int height,
+                                                 struct wl_shm_buffer *
+                                                   shm_buffer,
+                                                 int dst_x,
+                                                 int dst_y,
+                                                 int level,
+                                                 CoglError **error);
+
 COGL_END_DECLS
 
 #endif /* __COGL_WAYLAND_SERVER_H */
diff --git a/examples/cogland.c b/examples/cogland.c
index 82876c2..819605e 100644
--- a/examples/cogland.c
+++ b/examples/cogland.c
@@ -447,40 +447,16 @@ surface_damaged (CoglandSurface *surface,
 
       if (shm_buffer)
         {
-          CoglPixelFormat format;
-          int stride = wl_shm_buffer_get_stride (shm_buffer);
-          const uint8_t *data = wl_shm_buffer_get_data (shm_buffer);
-
-          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;
-              break;
-            case WL_SHM_FORMAT_XRGB8888:
-              format = COGL_PIXEL_FORMAT_ARGB_8888;
-              break;
-#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
-            case WL_SHM_FORMAT_ARGB8888:
-              format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
-              break;
-            case WL_SHM_FORMAT_XRGB8888:
-              format = COGL_PIXEL_FORMAT_BGRA_8888;
-              break;
-#endif
-            default:
-              g_warn_if_reached ();
-              format = COGL_PIXEL_FORMAT_ARGB_8888;
-            }
-
-          cogl_texture_set_region (COGL_TEXTURE (surface->texture),
-                                   width, height,
-                                   format,
-                                   stride,
-                                   data + x * 4 + y * stride,
-                                   x, y, /* dst_x/y */
-                                   0, /* level */
-                                   NULL /* error */);
+          CoglTexture *texture = COGL_TEXTURE (surface->texture);
+
+          cogl_wayland_texture_set_region_from_shm_buffer (texture,
+                                                           x, y,
+                                                           width,
+                                                           height,
+                                                           shm_buffer,
+                                                           x, y,
+                                                           0, /* level */
+                                                           NULL);
         }
     }
 
-- 
1.8.3.1



More information about the Cogl mailing list