[mutter] MetaCursorSprite: Put renderer specific code in the renderer



commit d3fdaa3232e4ff258f86f3020c2814385ef581e8
Author: Jonas Ådahl <jadahl gmail com>
Date:   Wed Mar 11 11:16:58 2015 +0800

    MetaCursorSprite: Put renderer specific code in the renderer
    
    There were lots of code handling the native renderer specific cases;
    move these parts to the renderer. Note that this causes the X11 case to
    always generate the texture which is a waste of memory, but his
    regression will be fixed in a following commit.
    
    The lazy loading of the texture was removed because it was eventually
    always loaded anyway indirectly by the renderer to calculate the
    current rect.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=744932

 src/backends/meta-cursor-renderer.c               |   25 ++
 src/backends/meta-cursor-renderer.h               |   22 ++
 src/backends/meta-cursor.c                        |  254 ++++-----------------
 src/backends/meta-cursor.h                        |   12 +-
 src/backends/native/meta-cursor-renderer-native.c |  210 ++++++++++++++++-
 5 files changed, 294 insertions(+), 229 deletions(-)
---
diff --git a/src/backends/meta-cursor-renderer.c b/src/backends/meta-cursor-renderer.c
index 5509288..689ac26 100644
--- a/src/backends/meta-cursor-renderer.c
+++ b/src/backends/meta-cursor-renderer.c
@@ -181,3 +181,28 @@ meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer)
 
   return &priv->current_rect;
 }
+
+#ifdef HAVE_WAYLAND
+void
+meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
+                                                    MetaCursorSprite   *cursor_sprite,
+                                                    struct wl_resource *buffer)
+{
+
+  MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer);
+
+  if (renderer_class->realize_cursor_from_wl_buffer)
+    renderer_class->realize_cursor_from_wl_buffer (renderer, cursor_sprite, buffer);
+}
+#endif
+
+void
+meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
+                                                  MetaCursorSprite   *cursor_sprite,
+                                                  XcursorImage       *xc_image)
+{
+  MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer);
+
+  if (renderer_class->realize_cursor_from_xcursor)
+    renderer_class->realize_cursor_from_xcursor (renderer, cursor_sprite, xc_image);
+}
diff --git a/src/backends/meta-cursor-renderer.h b/src/backends/meta-cursor-renderer.h
index 7a554e8..337d5c1 100644
--- a/src/backends/meta-cursor-renderer.h
+++ b/src/backends/meta-cursor-renderer.h
@@ -26,6 +26,10 @@
 #define META_CURSOR_RENDERER_H
 
 #include <glib-object.h>
+#include <X11/Xcursor/Xcursor.h>
+#ifdef HAVE_WAYLAND
+#include <wayland-server.h>
+#endif
 
 #include <meta/screen.h>
 #include "meta-cursor.h"
@@ -39,6 +43,14 @@ struct _MetaCursorRendererClass
   GObjectClass parent_class;
 
   gboolean (* update_cursor) (MetaCursorRenderer *renderer);
+#ifdef HAVE_WAYLAND
+  void (* realize_cursor_from_wl_buffer) (MetaCursorRenderer *renderer,
+                                          MetaCursorSprite *cursor_sprite,
+                                          struct wl_resource *buffer);
+#endif
+  void (* realize_cursor_from_xcursor) (MetaCursorRenderer *renderer,
+                                        MetaCursorSprite *cursor_sprite,
+                                        XcursorImage *xc_image);
 };
 
 GType meta_cursor_renderer_get_type (void) G_GNUC_CONST;
@@ -55,4 +67,14 @@ void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer);
 MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
 const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer);
 
+#ifdef HAVE_WAYLAND
+void meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
+                                                         MetaCursorSprite   *cursor_sprite,
+                                                         struct wl_resource *buffer);
+#endif
+
+void meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
+                                                       MetaCursorSprite   *cursor_sprite,
+                                                       XcursorImage       *xc_image);
+
 #endif /* META_CURSOR_RENDERER_H */
diff --git a/src/backends/meta-cursor.c b/src/backends/meta-cursor.c
index 706984d..8c09516 100644
--- a/src/backends/meta-cursor.c
+++ b/src/backends/meta-cursor.c
@@ -29,11 +29,6 @@
 #include "screen-private.h"
 #include "meta-backend-private.h"
 
-#ifdef HAVE_NATIVE_BACKEND
-#include <gbm.h>
-#include "backends/native/meta-cursor-renderer-native.h"
-#endif
-
 #include <string.h>
 
 #include <X11/cursorfont.h>
@@ -48,10 +43,6 @@ typedef struct
 {
   CoglTexture2D *texture;
   int hot_x, hot_y;
-
-#ifdef HAVE_NATIVE_BACKEND
-  struct gbm_bo *bo;
-#endif
 } MetaCursorImage;
 
 struct _MetaCursorSprite
@@ -74,11 +65,6 @@ meta_cursor_image_free (MetaCursorImage *image)
 {
   if (image->texture)
     cogl_object_unref (image->texture);
-
-#ifdef HAVE_NATIVE_BACKEND
-  if (image->bo)
-    gbm_bo_destroy (image->bo);
-#endif
 }
 
 static const char *
@@ -144,81 +130,13 @@ load_cursor_on_client (MetaCursor cursor)
                                    meta_prefs_get_cursor_size ());
 }
 
-#ifdef HAVE_NATIVE_BACKEND
-static void
-get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
-{
-  MetaBackend *meta_backend = meta_get_backend ();
-  MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
-
-  if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
-    {
-      meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, 
cursor_height);
-      return;
-    }
-
-  g_assert_not_reached ();
-}
-#endif
-
-#ifdef HAVE_NATIVE_BACKEND
 static void
-meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
-                                   MetaCursorImage   *image,
-                                   uint8_t           *pixels,
-                                   uint               width,
-                                   uint               height,
-                                   int                rowstride,
-                                   uint32_t           gbm_format)
-{
-  uint64_t cursor_width, cursor_height;
-  get_hardware_cursor_size (&cursor_width, &cursor_height);
-
-  if (width > cursor_width || height > cursor_height)
-    {
-      meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
-                    (unsigned int)cursor_width, (unsigned int)cursor_height);
-      return;
-    }
-
-  if (gbm_device_is_format_supported (gbm, gbm_format,
-                                      GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
-    {
-      uint8_t buf[4 * cursor_width * cursor_height];
-      uint i;
-
-      image->bo = gbm_bo_create (gbm, cursor_width, cursor_height,
-                                 gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
-
-      memset (buf, 0, sizeof(buf));
-      for (i = 0; i < height; i++)
-        memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
-
-      gbm_bo_write (image->bo, buf, cursor_width * cursor_height * 4);
-    }
-  else
-    meta_warning ("HW cursor for format %d not supported\n", gbm_format);
-}
-#endif
-
-#ifdef HAVE_NATIVE_BACKEND
-static struct gbm_device *
-get_gbm_device (void)
+meta_cursor_sprite_load_from_xcursor_image (MetaCursorSprite *self,
+                                            XcursorImage     *xc_image)
 {
+  MetaCursorImage *image = &self->image;
   MetaBackend *meta_backend = meta_get_backend ();
   MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
-
-  if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
-    return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
-  else
-    return NULL;
-}
-#endif
-
-static void
-meta_cursor_image_load_from_xcursor_image (MetaCursorImage   *image,
-                                           XcursorImage      *xc_image)
-{
   uint width, height, rowstride;
   CoglPixelFormat cogl_format;
   ClutterBackend *clutter_backend;
@@ -246,15 +164,7 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage   *image,
                                                   (uint8_t *) xc_image->pixels,
                                                   NULL);
 
-#ifdef HAVE_NATIVE_BACKEND
-  struct gbm_device *gbm = get_gbm_device ();
-  if (gbm)
-    meta_cursor_image_load_gbm_buffer (gbm,
-                                       image,
-                                       (uint8_t *) xc_image->pixels,
-                                       width, height, rowstride,
-                                       GBM_FORMAT_ARGB8888);
-#endif
+  meta_cursor_renderer_realize_cursor_from_xcursor (renderer, self, xc_image);
 }
 
 static XcursorImage *
@@ -278,7 +188,7 @@ meta_cursor_sprite_tick_frame (MetaCursorSprite *self)
 
   meta_cursor_image_free (&self->image);
   image = meta_cursor_sprite_get_current_frame_image (self);
-  meta_cursor_image_load_from_xcursor_image (&self->image, image);
+  meta_cursor_sprite_load_from_xcursor_image (self, image);
 }
 
 guint
@@ -297,36 +207,22 @@ meta_cursor_sprite_is_animated (MetaCursorSprite *self)
           self->xcursor_images->nimage > 1);
 }
 
-static void
-load_cursor_image (MetaCursorSprite *self)
-{
-  XcursorImage *image;
-
-  /* Either cursors are loaded from X cursors or buffers. Since
-   * buffers are converted over immediately, we can make sure to
-   * load this directly. */
-  g_assert (self->cursor != META_CURSOR_NONE);
-
-  if (!self->xcursor_images)
-    {
-      self->current_frame = 0;
-      self->xcursor_images = load_cursor_on_client (self->cursor);
-      if (!self->xcursor_images)
-        meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
-    }
-
-  image = meta_cursor_sprite_get_current_frame_image (self);
-  meta_cursor_image_load_from_xcursor_image (&self->image, image);
-}
-
 MetaCursorSprite *
 meta_cursor_sprite_from_theme (MetaCursor cursor)
 {
   MetaCursorSprite *self;
+  XcursorImage *image;
 
   self = g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
 
   self->cursor = cursor;
+  self->current_frame = 0;
+  self->xcursor_images = load_cursor_on_client (self->cursor);
+  if (!self->xcursor_images)
+    meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
+
+  image = meta_cursor_sprite_get_current_frame_image (self);
+  meta_cursor_sprite_load_from_xcursor_image (self, image);
 
   return self;
 }
@@ -351,11 +247,15 @@ meta_cursor_sprite_from_texture (CoglTexture2D *texture,
 
 #ifdef HAVE_WAYLAND
 static void
-meta_cursor_image_load_from_buffer (MetaCursorImage    *image,
-                                    struct wl_resource *buffer,
-                                    int                 hot_x,
-                                    int                 hot_y)
+meta_cursor_sprite_load_from_buffer (MetaCursorSprite   *self,
+                                     struct wl_resource *buffer,
+                                     int                 hot_x,
+                                     int                 hot_y)
 {
+  MetaCursorImage *image = &self->image;
+  MetaBackend *meta_backend = meta_get_backend ();
+  MetaCursorRenderer *renderer =
+    meta_backend_get_cursor_renderer (meta_backend);
   ClutterBackend *backend;
   CoglContext *cogl_context;
 
@@ -367,76 +267,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage    *image,
 
   image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
 
-#ifdef HAVE_NATIVE_BACKEND
-  struct gbm_device *gbm = get_gbm_device ();
-  if (gbm)
-    {
-      uint32_t gbm_format;
-      uint64_t cursor_width, cursor_height;
-      uint width, height;
-
-      width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
-      height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
-
-      struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
-      if (shm_buffer)
-        {
-          int rowstride = wl_shm_buffer_get_stride (shm_buffer);
-
-          wl_shm_buffer_begin_access (shm_buffer);
-
-          switch (wl_shm_buffer_get_format (shm_buffer))
-            {
-#if G_BYTE_ORDER == G_BIG_ENDIAN
-            case WL_SHM_FORMAT_ARGB8888:
-              gbm_format = GBM_FORMAT_ARGB8888;
-              break;
-            case WL_SHM_FORMAT_XRGB8888:
-              gbm_format = GBM_FORMAT_XRGB8888;
-              break;
-#else
-            case WL_SHM_FORMAT_ARGB8888:
-              gbm_format = GBM_FORMAT_ARGB8888;
-              break;
-            case WL_SHM_FORMAT_XRGB8888:
-              gbm_format = GBM_FORMAT_XRGB8888;
-              break;
-#endif
-            default:
-              g_warn_if_reached ();
-              gbm_format = GBM_FORMAT_ARGB8888;
-            }
-
-          meta_cursor_image_load_gbm_buffer (gbm,
-                                             image,
-                                             (uint8_t *) wl_shm_buffer_get_data (shm_buffer),
-                                             width, height, rowstride,
-                                             gbm_format);
-
-          wl_shm_buffer_end_access (shm_buffer);
-        }
-      else
-        {
-          /* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme
-             size, so themed cursors must be padded with transparent pixels to fill the
-             overlay. This is trivial if we have CPU access to the data, but it's not
-             possible if the buffer is in GPU memory (and possibly tiled too), so if we
-             don't get the right size, we fallback to GL.
-          */
-          get_hardware_cursor_size (&cursor_width, &cursor_height);
-
-          if (width != cursor_width || height != cursor_height)
-            {
-              meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
-              return;
-            }
-
-          image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, buffer, GBM_BO_USE_CURSOR);
-          if (!image->bo)
-            meta_warning ("Importing HW cursor from wl_buffer failed\n");
-        }
-    }
-#endif
+  meta_cursor_renderer_realize_cursor_from_wl_buffer (renderer, self, buffer);
 }
 
 MetaCursorSprite *
@@ -448,7 +279,7 @@ meta_cursor_sprite_from_buffer (struct wl_resource *buffer,
 
   self = g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
 
-  meta_cursor_image_load_from_buffer (&self->image, buffer, hot_x, hot_y);
+  meta_cursor_sprite_load_from_buffer (self, buffer, hot_x, hot_y);
 
   return self;
 }
@@ -459,9 +290,6 @@ meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self,
                                      int              *hot_x,
                                      int              *hot_y)
 {
-  if (!self->image.texture)
-    load_cursor_image (self);
-
   if (hot_x)
     *hot_x = self->image.hot_x;
   if (hot_y)
@@ -470,27 +298,31 @@ meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self,
   return COGL_TEXTURE (self->image.texture);
 }
 
-#ifdef HAVE_NATIVE_BACKEND
-struct gbm_bo *
-meta_cursor_sprite_get_gbm_bo (MetaCursorSprite *self,
-                               int              *hot_x,
-                               int              *hot_y)
+MetaCursor
+meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self)
 {
-  if (!self->image.bo)
-    load_cursor_image (self);
+  return self->cursor;
+}
 
-  if (hot_x)
-    *hot_x = self->image.hot_x;
-  if (hot_y)
-    *hot_y = self->image.hot_y;
-  return self->image.bo;
+void
+meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
+                                int              *hot_x,
+                                int              *hot_y)
+{
+  *hot_x = self->image.hot_x;
+  *hot_y = self->image.hot_y;
 }
-#endif
 
-MetaCursor
-meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self)
+guint
+meta_cursor_sprite_get_width (MetaCursorSprite *self)
 {
-  return self->cursor;
+  return cogl_texture_get_width (COGL_TEXTURE (self->image.texture));
+}
+
+guint
+meta_cursor_sprite_get_height (MetaCursorSprite *self)
+{
+  return cogl_texture_get_height (COGL_TEXTURE (self->image.texture));
 }
 
 static void
diff --git a/src/backends/meta-cursor.h b/src/backends/meta-cursor.h
index a9e3a9f..f0b014b 100644
--- a/src/backends/meta-cursor.h
+++ b/src/backends/meta-cursor.h
@@ -54,11 +54,13 @@ CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self,
                                                   int              *hot_x,
                                                   int              *hot_y);
 
-#ifdef HAVE_NATIVE_BACKEND
-struct gbm_bo *meta_cursor_sprite_get_gbm_bo (MetaCursorSprite *self,
-                                              int              *hot_x,
-                                              int              *hot_y);
-#endif
+void meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
+                                     int              *hot_x,
+                                     int              *hot_y);
+
+guint meta_cursor_sprite_get_width (MetaCursorSprite *self);
+
+guint meta_cursor_sprite_get_height (MetaCursorSprite *self);
 
 gboolean meta_cursor_sprite_is_animated            (MetaCursorSprite *self);
 void     meta_cursor_sprite_tick_frame             (MetaCursorSprite *self);
diff --git a/src/backends/native/meta-cursor-renderer-native.c 
b/src/backends/native/meta-cursor-renderer-native.c
index 81ab4d0..b9e4b0d 100644
--- a/src/backends/native/meta-cursor-renderer-native.c
+++ b/src/backends/native/meta-cursor-renderer-native.c
@@ -26,9 +26,11 @@
 
 #include "meta-cursor-renderer-native.h"
 
+#include <string.h>
 #include <gbm.h>
 #include <xf86drm.h>
 
+#include <meta/util.h>
 #include "meta-monitor-manager-private.h"
 
 #ifndef DRM_CAP_CURSOR_WIDTH
@@ -38,6 +40,8 @@
 #define DRM_CAP_CURSOR_HEIGHT 0x9
 #endif
 
+static GQuark quark_cursor_sprite = 0;
+
 struct _MetaCursorRendererNativePrivate
 {
   gboolean has_hw_cursor;
@@ -70,6 +74,28 @@ meta_cursor_renderer_native_finalize (GObject *object)
   G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
 }
 
+static struct gbm_bo *
+get_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
+{
+  return g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
+}
+
+static void
+cursor_gbm_bo_free (gpointer data)
+{
+  if (!data)
+    return;
+
+  gbm_bo_destroy ((struct gbm_bo *)data);
+}
+
+static void
+set_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite, struct gbm_bo *bo)
+{
+  g_object_set_qdata_full (G_OBJECT (cursor_sprite), quark_cursor_sprite,
+                           bo, cursor_gbm_bo_free);
+}
+
 static void
 set_crtc_cursor (MetaCursorRendererNative *native,
                  MetaCRTC                 *crtc,
@@ -89,9 +115,10 @@ set_crtc_cursor (MetaCursorRendererNative *native,
       union gbm_bo_handle handle;
       int hot_x, hot_y;
 
-      bo = meta_cursor_sprite_get_gbm_bo (cursor_sprite, &hot_x, &hot_y);
-
+      bo = get_cursor_sprite_gbm_bo (cursor_sprite);
       handle = gbm_bo_get_handle (bo);
+      meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y);
+
       drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
                          priv->cursor_width, priv->cursor_height, hot_x, hot_y);
     }
@@ -147,7 +174,7 @@ should_have_hw_cursor (MetaCursorRenderer *renderer)
   MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer);
 
   if (cursor_sprite)
-    return (meta_cursor_sprite_get_gbm_bo (cursor_sprite, NULL, NULL) != NULL);
+    return (get_cursor_sprite_gbm_bo (cursor_sprite) != NULL);
   else
     return FALSE;
 }
@@ -220,6 +247,165 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
 }
 
 static void
+get_hardware_cursor_size (MetaCursorRendererNative *native,
+                          uint64_t *width, uint64_t *height)
+{
+  MetaCursorRendererNativePrivate *priv =
+    meta_cursor_renderer_native_get_instance_private (native);
+
+  *width = priv->cursor_width;
+  *height = priv->cursor_height;
+}
+
+static void
+load_cursor_sprite_gbm_buffer (MetaCursorRendererNative *native,
+                               MetaCursorSprite         *cursor_sprite,
+                               uint8_t                  *pixels,
+                               uint                      width,
+                               uint                      height,
+                               int                       rowstride,
+                               uint32_t                  gbm_format)
+{
+  MetaCursorRendererNativePrivate *priv =
+    meta_cursor_renderer_native_get_instance_private (native);
+  uint64_t cursor_width, cursor_height;
+
+  get_hardware_cursor_size (native, &cursor_width, &cursor_height);
+
+  if (width > cursor_width || height > cursor_height)
+    {
+      meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
+                    (unsigned int)cursor_width, (unsigned int)cursor_height);
+      return;
+    }
+
+  if (gbm_device_is_format_supported (priv->gbm, gbm_format,
+                                      GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
+    {
+      struct gbm_bo *bo;
+      uint8_t buf[4 * cursor_width * cursor_height];
+      uint i;
+
+      bo = gbm_bo_create (priv->gbm, cursor_width, cursor_height,
+                          gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
+
+      memset (buf, 0, sizeof(buf));
+      for (i = 0; i < height; i++)
+        memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
+
+      gbm_bo_write (bo, buf, cursor_width * cursor_height * 4);
+
+      set_cursor_sprite_gbm_bo (cursor_sprite, bo);
+    }
+  else
+    meta_warning ("HW cursor for format %d not supported\n", gbm_format);
+}
+
+#ifdef HAVE_WAYLAND
+static void
+meta_cursor_renderer_native_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
+                                                           MetaCursorSprite *cursor_sprite,
+                                                           struct wl_resource *buffer)
+{
+  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
+  MetaCursorRendererNativePrivate *priv =
+    meta_cursor_renderer_native_get_instance_private (native);
+  uint32_t gbm_format;
+  uint64_t cursor_width, cursor_height;
+  uint width, height;
+
+  width = meta_cursor_sprite_get_width (cursor_sprite);
+  height = meta_cursor_sprite_get_height (cursor_sprite);
+
+  struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
+  if (shm_buffer)
+    {
+      int rowstride = wl_shm_buffer_get_stride (shm_buffer);
+      uint8_t *buffer_data;
+
+      wl_shm_buffer_begin_access (shm_buffer);
+
+      switch (wl_shm_buffer_get_format (shm_buffer))
+        {
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+        case WL_SHM_FORMAT_ARGB8888:
+          gbm_format = GBM_FORMAT_ARGB8888;
+          break;
+        case WL_SHM_FORMAT_XRGB8888:
+          gbm_format = GBM_FORMAT_XRGB8888;
+          break;
+#else
+        case WL_SHM_FORMAT_ARGB8888:
+          gbm_format = GBM_FORMAT_ARGB8888;
+          break;
+        case WL_SHM_FORMAT_XRGB8888:
+          gbm_format = GBM_FORMAT_XRGB8888;
+          break;
+#endif
+        default:
+          g_warn_if_reached ();
+          gbm_format = GBM_FORMAT_ARGB8888;
+        }
+
+      buffer_data = wl_shm_buffer_get_data (shm_buffer);
+      load_cursor_sprite_gbm_buffer (native,
+                                     cursor_sprite,
+                                     buffer_data,
+                                     width, height, rowstride,
+                                     gbm_format);
+
+      wl_shm_buffer_end_access (shm_buffer);
+    }
+  else
+    {
+      struct gbm_bo *bo;
+
+      /* HW cursors have a predefined size (at least 64x64), which usually is
+       * bigger than cursor theme size, so themed cursors must be padded with
+       * transparent pixels to fill the overlay. This is trivial if we have CPU
+       * access to the data, but it's not possible if the buffer is in GPU
+       * memory (and possibly tiled too), so if we don't get the right size, we
+       * fallback to GL. */
+      get_hardware_cursor_size (native, &cursor_width, &cursor_height);
+
+      if (width != cursor_width || height != cursor_height)
+        {
+          meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
+          return;
+        }
+
+      bo = gbm_bo_import (priv->gbm,
+                          GBM_BO_IMPORT_WL_BUFFER,
+                          buffer,
+                          GBM_BO_USE_CURSOR);
+      if (!bo)
+        {
+          meta_warning ("Importing HW cursor from wl_buffer failed\n");
+          return;
+        }
+
+      set_cursor_sprite_gbm_bo (cursor_sprite, bo);
+    }
+}
+#endif
+
+static void
+meta_cursor_renderer_native_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
+                                                         MetaCursorSprite *cursor_sprite,
+                                                         XcursorImage *xc_image)
+{
+  MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
+
+  load_cursor_sprite_gbm_buffer (native,
+                                 cursor_sprite,
+                                 (uint8_t *) xc_image->pixels,
+                                 xc_image->width,
+                                 xc_image->height,
+                                 xc_image->width * 4,
+                                 GBM_FORMAT_ARGB8888);
+}
+
+static void
 meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
 {
   MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass);
@@ -227,6 +413,14 @@ meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
 
   object_class->finalize = meta_cursor_renderer_native_finalize;
   renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor;
+#ifdef HAVE_WAYLAND
+  renderer_class->realize_cursor_from_wl_buffer =
+    meta_cursor_renderer_native_realize_cursor_from_wl_buffer;
+#endif
+  renderer_class->realize_cursor_from_xcursor =
+    meta_cursor_renderer_native_realize_cursor_from_xcursor;
+
+  quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native");
 }
 
 static void
@@ -280,16 +474,6 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
 }
 
 void
-meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native,
-                                             uint64_t *width, uint64_t *height)
-{
-  MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
-
-  *width = priv->cursor_width;
-  *height = priv->cursor_height;
-}
-
-void
 meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
 {
   update_hw_cursor (native, TRUE);


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