diff --git a/src/backends/meta-cursor.c b/src/backends/meta-cursor.c index 592e26f32..3695d8131 100644 --- a/src/backends/meta-cursor.c +++ b/src/backends/meta-cursor.c @@ -139,35 +139,56 @@ load_cursor_on_client (MetaCursor cursor) meta_prefs_get_cursor_size ()); } +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 883ddef4d..ca29882fb 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 +#include #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 } @@ -198,6 +218,16 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native) return priv->gbm; } +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) { diff --git a/src/backends/native/meta-cursor-renderer-native.h b/src/backends/native/meta-cursor-renderer-native.h index 80836a78f..e332ede97 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 */