[mutter] Support for hardware cursor sizes other than 64x64 on wayland



commit 488dd0b402dc8c56a70f995a7456c2ff511a818b
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Wed Sep 24 15:40:09 2014 -0600

    Support for hardware cursor sizes other than 64x64 on wayland
    
    Use the new DRM capabilities to figure out the correct cursor size, and
    make sure that matches instead of hardcoding 64x64. This fixes incorrect
    rendering on some newer AMD cards that support 256x256 cursors.
    
    Based heavily on a patch by:
    Alvaro Fernando GarcĂ­a <alvarofernandogarcia gmail com>

 src/backends/meta-cursor.c                        |   77 +++++++++++++-------
 src/backends/native/meta-cursor-renderer-native.c |   40 +++++++++--
 src/backends/native/meta-cursor-renderer-native.h |    1 +
 3 files changed, 86 insertions(+), 32 deletions(-)
---
diff --git a/src/backends/meta-cursor.c b/src/backends/meta-cursor.c
index 592e26f..3695d81 100644
--- a/src/backends/meta-cursor.c
+++ b/src/backends/meta-cursor.c
@@ -140,34 +140,55 @@ load_cursor_on_client (MetaCursor cursor)
 }
 
 static void
+get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
+{
+#ifdef HAVE_NATIVE_BACKEND
+  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;
+    }
+#endif
+
+  g_assert_not_reached ();
+}
+
+static void
 meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
                                    MetaCursorImage   *image,
                                    uint8_t           *pixels,
-                                   int                width,
-                                   int                height,
+                                   uint               width,
+                                   uint               height,
                                    int                rowstride,
                                    uint32_t           gbm_format)
 {
-  if (width > 64 || height > 64)
+  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 64x64)\n");
+      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_64X64 | GBM_BO_USE_WRITE))
+                                      GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
     {
-      uint8_t buf[4 * 64 * 64];
-      int i;
+      uint8_t buf[4 * cursor_width * cursor_height];
+      uint i;
 
-      image->bo = gbm_bo_create (gbm, 64, 64,
-                                 gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
+      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 * 64, pixels + i * rowstride, width * 4);
+        memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
 
-      gbm_bo_write (image->bo, buf, 64 * 64 * 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);
@@ -191,7 +212,7 @@ static void
 meta_cursor_image_load_from_xcursor_image (MetaCursorImage   *image,
                                            XcursorImage      *xc_image)
 {
-  int width, height, rowstride;
+  uint width, height, rowstride;
   CoglPixelFormat cogl_format;
   uint32_t gbm_format;
   ClutterBackend *clutter_backend;
@@ -262,7 +283,8 @@ meta_cursor_image_load_from_buffer (MetaCursorImage    *image,
   CoglContext *cogl_context;
   struct wl_shm_buffer *shm_buffer;
   uint32_t gbm_format;
-  int width, height;
+  uint64_t cursor_width, cursor_height;
+  uint width, height;
 
   image->hot_x = hot_x;
   image->hot_y = hot_y;
@@ -313,22 +335,23 @@ meta_cursor_image_load_from_buffer (MetaCursorImage    *image,
     }
   else
     {
-      /* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
-         that, 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.
-      */
-      if (width != 64 || height != 64)
-        {
-          meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
-          return;
-        }
-
       if (gbm)
         {
-          image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
-                                     buffer, GBM_BO_USE_CURSOR_64X64);
+          /* 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");
         }
diff --git a/src/backends/native/meta-cursor-renderer-native.c 
b/src/backends/native/meta-cursor-renderer-native.c
index 883ddef..ca29882 100644
--- a/src/backends/native/meta-cursor-renderer-native.c
+++ b/src/backends/native/meta-cursor-renderer-native.c
@@ -27,16 +27,27 @@
 #include "meta-cursor-renderer-native.h"
 
 #include <gbm.h>
+#include <xf86drm.h>
 
 #include "meta-cursor-private.h"
 #include "meta-monitor-manager.h"
 
+#ifndef DRM_CAP_CURSOR_WIDTH
+#define DRM_CAP_CURSOR_WIDTH 0x8
+#endif
+#ifndef DRM_CAP_CURSOR_HEIGHT
+#define DRM_CAP_CURSOR_HEIGHT 0x9
+#endif
+
 struct _MetaCursorRendererNativePrivate
 {
   gboolean has_hw_cursor;
 
   int drm_fd;
   struct gbm_device *gbm;
+
+  uint64_t cursor_width;
+  uint64_t cursor_height;
 };
 typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
 
@@ -71,17 +82,13 @@ set_crtc_cursor (MetaCursorRendererNative *native,
     {
       struct gbm_bo *bo;
       union gbm_bo_handle handle;
-      int width, height;
       int hot_x, hot_y;
 
       bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
 
       handle = gbm_bo_get_handle (bo);
-      width = gbm_bo_get_width (bo);
-      height = gbm_bo_get_height (bo);
-
       drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
-                         width, height, hot_x, hot_y);
+                         priv->cursor_width, priv->cursor_height, hot_x, hot_y);
     }
   else
     {
@@ -186,6 +193,19 @@ meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
       CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
       priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
       priv->gbm = gbm_create_device (priv->drm_fd);
+
+      uint64_t width, height;
+      if (drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
+          drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
+        {
+          priv->cursor_width = width;
+          priv->cursor_height = height;
+        }
+      else
+        {
+          priv->cursor_width = 64;
+          priv->cursor_height = 64;
+        }
     }
 #endif
 }
@@ -199,6 +219,16 @@ 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);
diff --git a/src/backends/native/meta-cursor-renderer-native.h 
b/src/backends/native/meta-cursor-renderer-native.h
index 80836a7..e332ede 100644
--- a/src/backends/native/meta-cursor-renderer-native.h
+++ b/src/backends/native/meta-cursor-renderer-native.h
@@ -50,6 +50,7 @@ struct _MetaCursorRendererNativeClass
 GType meta_cursor_renderer_native_get_type (void) G_GNUC_CONST;
 
 struct gbm_device * meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *renderer);
+void meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native, uint64_t *width, 
uint64_t *height);
 void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer);
 
 #endif /* META_CURSOR_RENDERER_NATIVE_H */


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