diff --git a/src/Makefile.am b/src/Makefile.am index 04a9c046f..13e7c8e9a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,6 +72,8 @@ libmutter_la_SOURCES = \ backends/edid.h \ backends/native/meta-backend-native.c \ backends/native/meta-backend-native.h \ + backends/native/meta-cursor-renderer-native.c \ + backends/native/meta-cursor-renderer-native.h \ backends/native/meta-idle-monitor-native.c \ backends/native/meta-idle-monitor-native.h \ backends/native/meta-monitor-manager-kms.c \ diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h index 1f866d08d..5435fbefd 100644 --- a/src/backends/meta-backend-private.h +++ b/src/backends/meta-backend-private.h @@ -54,6 +54,7 @@ struct _MetaBackendClass MetaIdleMonitor * (* create_idle_monitor) (MetaBackend *backend, int device_id); MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend); + MetaCursorRenderer * (* create_cursor_renderer) (MetaBackend *backend); }; #endif /* META_BACKEND_PRIVATE_H */ diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c index a753c07c4..d9054c6f1 100644 --- a/src/backends/meta-backend.c +++ b/src/backends/meta-backend.c @@ -78,12 +78,24 @@ meta_backend_finalize (GObject *object) G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object); } +static MetaCursorRenderer * +meta_backend_create_cursor_renderer (MetaBackend *backend) +{ + return META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend); +} + static void meta_backend_real_post_init (MetaBackend *backend) { MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - priv->cursor_renderer = meta_cursor_renderer_new (); + priv->cursor_renderer = meta_backend_create_cursor_renderer (backend); +} + +static MetaCursorRenderer * +meta_backend_real_create_cursor_renderer (MetaBackend *backend) +{ + return meta_cursor_renderer_new (); } static void @@ -95,6 +107,7 @@ meta_backend_class_init (MetaBackendClass *klass) object_class->finalize = meta_backend_finalize; klass->post_init = meta_backend_real_post_init; + klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer; } static void diff --git a/src/backends/meta-cursor-renderer.c b/src/backends/meta-cursor-renderer.c index 767780b59..910223f3f 100644 --- a/src/backends/meta-cursor-renderer.c +++ b/src/backends/meta-cursor-renderer.c @@ -30,151 +30,22 @@ #include #include #include -#include -#include "meta-monitor-manager.h" #include "meta-stage.h" #include "wayland/meta-wayland-private.h" struct _MetaCursorRendererPrivate { - gboolean has_hw_cursor; - int current_x, current_y; MetaRectangle current_rect; - int drm_fd; - struct gbm_device *gbm; - MetaCursorReference *displayed_cursor; }; typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate; G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT); -static void -set_crtc_cursor (MetaCursorRenderer *renderer, - MetaCRTC *crtc, - MetaCursorReference *cursor, - gboolean force) -{ - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - - if (crtc->cursor == cursor && !force) - return; - - crtc->cursor = cursor; - - if (cursor) - { - 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); - } - else - { - drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0); - } -} - -static void -update_hw_cursor (MetaCursorRenderer *renderer, - gboolean force) -{ - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - MetaRectangle *cursor_rect = &priv->current_rect; - MetaMonitorManager *monitors; - MetaCRTC *crtcs; - unsigned int i, n_crtcs; - - monitors = meta_monitor_manager_get (); - meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL); - - for (i = 0; i < n_crtcs; i++) - { - gboolean crtc_should_have_cursor; - MetaCursorReference *cursor; - MetaRectangle *crtc_rect; - - crtc_rect = &crtcs[i].rect; - - crtc_should_have_cursor = (priv->has_hw_cursor && meta_rectangle_overlap (cursor_rect, crtc_rect)); - if (crtc_should_have_cursor) - cursor = priv->displayed_cursor; - else - cursor = NULL; - - set_crtc_cursor (renderer, &crtcs[i], cursor, force); - - if (cursor) - { - drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id, - cursor_rect->x - crtc_rect->x, - cursor_rect->y - crtc_rect->y); - } - } -} - -static void -on_monitors_changed (MetaMonitorManager *monitors, - MetaCursorRenderer *renderer) -{ - /* Our tracking is all messed up, so force an update. */ - update_hw_cursor (renderer, TRUE); -} - -static void -meta_cursor_renderer_finalize (GObject *object) -{ - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object); - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - - if (priv->gbm) - gbm_device_destroy (priv->gbm); - - G_OBJECT_CLASS (meta_cursor_renderer_parent_class)->finalize (object); -} - -static void -meta_cursor_renderer_class_init (MetaCursorRendererClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_cursor_renderer_finalize; -} - -static void -meta_cursor_renderer_init (MetaCursorRenderer *renderer) -{ - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); - MetaMonitorManager *monitors; - - monitors = meta_monitor_manager_get (); - g_signal_connect_object (monitors, "monitors-changed", - G_CALLBACK (on_monitors_changed), renderer, 0); - -#if defined(CLUTTER_WINDOWING_EGL) - if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) - { - 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); - } -#endif -} - static void queue_redraw (MetaCursorRenderer *renderer) { @@ -197,15 +68,21 @@ queue_redraw (MetaCursorRenderer *renderer) &priv->current_rect); } -static gboolean -should_have_hw_cursor (MetaCursorRenderer *renderer) +static void +meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer) { - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); + queue_redraw (renderer); +} - if (priv->displayed_cursor) - return (meta_cursor_reference_get_gbm_bo (priv->displayed_cursor, NULL, NULL) != NULL); - else - return FALSE; +static void +meta_cursor_renderer_class_init (MetaCursorRendererClass *klass) +{ + klass->update_cursor = meta_cursor_renderer_real_update_cursor; +} + +static void +meta_cursor_renderer_init (MetaCursorRenderer *renderer) +{ } static void @@ -233,14 +110,7 @@ update_cursor (MetaCursorRenderer *renderer) priv->current_rect.height = 0; } - if (meta_is_wayland_compositor ()) - { - priv->has_hw_cursor = should_have_hw_cursor (renderer); - update_hw_cursor (renderer, FALSE); - - if (!priv->has_hw_cursor) - queue_redraw (renderer); - } + META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer); } MetaCursorRenderer * @@ -276,18 +146,18 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, update_cursor (renderer); } -void -meta_cursor_renderer_force_update (MetaCursorRenderer *renderer) -{ - g_assert (meta_is_wayland_compositor ()); - - update_hw_cursor (renderer, TRUE); -} - -struct gbm_device * -meta_cursor_renderer_get_gbm_device (MetaCursorRenderer *renderer) +MetaCursorReference * +meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer) { MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - return priv->gbm; + return priv->displayed_cursor; +} + +const MetaRectangle * +meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer) +{ + MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); + + return &priv->current_rect; } diff --git a/src/backends/meta-cursor-renderer.h b/src/backends/meta-cursor-renderer.h index 02a417036..ec5d4e846 100644 --- a/src/backends/meta-cursor-renderer.h +++ b/src/backends/meta-cursor-renderer.h @@ -50,6 +50,8 @@ struct _MetaCursorRenderer struct _MetaCursorRendererClass { GObjectClass parent_class; + + void (* update_cursor) (MetaCursorRenderer *renderer); }; GType meta_cursor_renderer_get_type (void) G_GNUC_CONST; @@ -62,8 +64,7 @@ void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer, void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, int x, int y); -void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer); - -struct gbm_device * meta_cursor_renderer_get_gbm_device (MetaCursorRenderer *renderer); +MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer); +const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer); #endif /* META_CURSOR_RENDERER_H */ diff --git a/src/backends/meta-cursor.c b/src/backends/meta-cursor.c index 6df9a3978..8357eec9f 100644 --- a/src/backends/meta-cursor.c +++ b/src/backends/meta-cursor.c @@ -29,6 +29,7 @@ #include "screen-private.h" #include "meta-backend.h" #include "meta-cursor-tracker-private.h" +#include "backends/native/meta-cursor-renderer-native.h" #include @@ -181,7 +182,11 @@ get_gbm_device (void) { MetaBackend *meta_backend = meta_get_backend (); MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend); - return meta_cursor_renderer_get_gbm_device (renderer); + + if (META_IS_CURSOR_RENDERER_NATIVE (renderer)) + return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer)); + else + return NULL; } static void diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index 6648f6597..7a20e08e7 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -30,6 +30,7 @@ #include "meta-idle-monitor-native.h" #include "meta-monitor-manager-kms.h" +#include "meta-cursor-renderer-native.h" #include "meta-weston-launch.h" struct _MetaBackendNativePrivate @@ -164,6 +165,12 @@ meta_backend_native_create_monitor_manager (MetaBackend *backend) return g_object_new (META_TYPE_MONITOR_MANAGER_KMS, NULL); } +static MetaCursorRenderer * +meta_backend_native_create_cursor_renderer (MetaBackend *backend) +{ + return g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL); +} + static void meta_backend_native_class_init (MetaBackendNativeClass *klass) { @@ -172,6 +179,7 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass) backend_class->post_init = meta_backend_native_post_init; backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor; backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager; + backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer; } static void diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c new file mode 100644 index 000000000..ad823c678 --- /dev/null +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -0,0 +1,208 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2014 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Jasper St. Pierre + */ + +#include "config.h" + +#include "meta-cursor-renderer-native.h" + +#include + +#include "meta-cursor-private.h" +#include "meta-monitor-manager.h" + +struct _MetaCursorRendererNativePrivate +{ + gboolean has_hw_cursor; + + int drm_fd; + struct gbm_device *gbm; +}; +typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER); + +static void +meta_cursor_renderer_native_finalize (GObject *object) +{ + MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object); + MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer); + + if (priv->gbm) + gbm_device_destroy (priv->gbm); + + G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object); +} + +static void +set_crtc_cursor (MetaCursorRendererNative *native, + MetaCRTC *crtc, + MetaCursorReference *cursor, + gboolean force) +{ + MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); + + if (crtc->cursor == cursor && !force) + return; + + crtc->cursor = cursor; + + if (cursor) + { + 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); + } + else + { + drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0); + } +} + +static void +update_hw_cursor (MetaCursorRendererNative *native, + gboolean force) +{ + MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); + MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); + const MetaRectangle *cursor_rect = meta_cursor_renderer_get_rect (renderer); + MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer); + MetaMonitorManager *monitors; + MetaCRTC *crtcs; + unsigned int i, n_crtcs; + + monitors = meta_monitor_manager_get (); + meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL); + + for (i = 0; i < n_crtcs; i++) + { + gboolean crtc_should_have_cursor; + MetaCursorReference *crtc_cursor; + MetaRectangle *crtc_rect; + + crtc_rect = &crtcs[i].rect; + + crtc_should_have_cursor = (priv->has_hw_cursor && meta_rectangle_overlap (cursor_rect, crtc_rect)); + if (crtc_should_have_cursor) + crtc_cursor = cursor; + else + crtc_cursor = NULL; + + set_crtc_cursor (native, &crtcs[i], crtc_cursor, force); + + if (cursor) + { + drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id, + cursor_rect->x - crtc_rect->x, + cursor_rect->y - crtc_rect->y); + } + } +} + +static gboolean +should_have_hw_cursor (MetaCursorRenderer *renderer) +{ + MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer); + + if (cursor) + return (meta_cursor_reference_get_gbm_bo (cursor, NULL, NULL) != NULL); + else + return FALSE; +} + +static void +meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer) +{ + MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); + MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); + + priv->has_hw_cursor = should_have_hw_cursor (renderer); + update_hw_cursor (native, FALSE); + + /* Fall back to the stage-based cursor if we don't have HW cursors. */ + if (!priv->has_hw_cursor) + META_CURSOR_RENDERER_CLASS (meta_cursor_renderer_native_parent_class)->update_cursor (renderer); +} + +static void +meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass) +{ + MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_cursor_renderer_native_finalize; + renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor; +} + +static void +on_monitors_changed (MetaMonitorManager *monitors, + MetaCursorRendererNative *native) +{ + /* Our tracking is all messed up, so force an update. */ + update_hw_cursor (native, TRUE); +} + +static void +meta_cursor_renderer_native_init (MetaCursorRendererNative *native) +{ + MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); + CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); + MetaMonitorManager *monitors; + + monitors = meta_monitor_manager_get (); + g_signal_connect_object (monitors, "monitors-changed", + G_CALLBACK (on_monitors_changed), native, 0); + +#if defined(CLUTTER_WINDOWING_EGL) + if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) + { + 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); + } +#endif +} + +struct gbm_device * +meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native) +{ + MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); + + return priv->gbm; +} + +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 new file mode 100644 index 000000000..80836a78f --- /dev/null +++ b/src/backends/native/meta-cursor-renderer-native.h @@ -0,0 +1,55 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2014 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Jasper St. Pierre + */ + +#ifndef META_CURSOR_RENDERER_NATIVE_H +#define META_CURSOR_RENDERER_NATIVE_H + +#include "meta-cursor-renderer.h" + +#define META_TYPE_CURSOR_RENDERER_NATIVE (meta_cursor_renderer_native_get_type ()) +#define META_CURSOR_RENDERER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNative)) +#define META_CURSOR_RENDERER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNativeClass)) +#define META_IS_CURSOR_RENDERER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER_NATIVE)) +#define META_IS_CURSOR_RENDERER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_RENDERER_NATIVE)) +#define META_CURSOR_RENDERER_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNativeClass)) + +typedef struct _MetaCursorRendererNative MetaCursorRendererNative; +typedef struct _MetaCursorRendererNativeClass MetaCursorRendererNativeClass; + +struct _MetaCursorRendererNative +{ + MetaCursorRenderer parent; +}; + +struct _MetaCursorRendererNativeClass +{ + MetaCursorRendererClass parent_class; +}; + +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_force_update (MetaCursorRendererNative *renderer); + +#endif /* META_CURSOR_RENDERER_NATIVE_H */ diff --git a/src/backends/native/meta-weston-launch.c b/src/backends/native/meta-weston-launch.c index 049edb30a..1c98b26ba 100644 --- a/src/backends/native/meta-weston-launch.c +++ b/src/backends/native/meta-weston-launch.c @@ -44,6 +44,7 @@ #include "wayland/meta-wayland-private.h" #include "backends/meta-backend.h" +#include "meta-cursor-renderer-native.h" #include "meta-weston-launch.h" struct _MetaLauncher @@ -224,7 +225,7 @@ meta_launcher_enter (MetaLauncher *launcher) * update. */ clutter_actor_queue_redraw (compositor->stage); - meta_cursor_renderer_force_update (renderer); + meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer)); } }