diff options
Diffstat (limited to 'src/backends/native')
117 files changed, 0 insertions, 34626 deletions
diff --git a/src/backends/native/dbus-utils.c b/src/backends/native/dbus-utils.c deleted file mode 100644 index 79fafe881..000000000 --- a/src/backends/native/dbus-utils.c +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- 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 <jstpierre@mecheye.net> - */ - -#include "config.h" - -#include "backends/native/dbus-utils.h" - -#include <glib.h> - -/* Stolen from tp_escape_as_identifier, from tp-glib, - * which follows the same escaping convention as systemd. - */ -static inline gboolean -_esc_ident_bad (gchar c, gboolean is_first) -{ - return ((c < 'a' || c > 'z') && - (c < 'A' || c > 'Z') && - (c < '0' || c > '9' || is_first)); -} - -static gchar * -escape_dbus_component (const gchar *name) -{ - gboolean bad = FALSE; - size_t len = 0; - GString *op; - const gchar *ptr, *first_ok; - - g_return_val_if_fail (name != NULL, NULL); - - /* fast path for empty name */ - if (name[0] == '\0') - return g_strdup ("_"); - - for (ptr = name; *ptr; ptr++) - { - if (_esc_ident_bad (*ptr, ptr == name)) - { - bad = TRUE; - len += 3; - } - else - len++; - } - - /* fast path if it's clean */ - if (!bad) - return g_strdup (name); - - /* If strictly less than ptr, first_ok is the first uncopied safe character. - */ - first_ok = name; - op = g_string_sized_new (len); - for (ptr = name; *ptr; ptr++) - { - if (_esc_ident_bad (*ptr, ptr == name)) - { - /* copy preceding safe characters if any */ - if (first_ok < ptr) - { - g_string_append_len (op, first_ok, ptr - first_ok); - } - /* escape the unsafe character */ - g_string_append_printf (op, "_%02x", (unsigned char)(*ptr)); - /* restart after it */ - first_ok = ptr + 1; - } - } - /* copy trailing safe characters if any */ - if (first_ok < ptr) - { - g_string_append_len (op, first_ok, ptr - first_ok); - } - return g_string_free (op, FALSE); -} - -char * -get_escaped_dbus_path (const char *prefix, - const char *component) -{ - char *escaped_component = escape_dbus_component (component); - char *path = g_strconcat (prefix, "/", escaped_component, NULL); - - g_free (escaped_component); - return path; -} diff --git a/src/backends/native/dbus-utils.h b/src/backends/native/dbus-utils.h deleted file mode 100644 index ee56c455a..000000000 --- a/src/backends/native/dbus-utils.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- 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 <jstpierre@mecheye.net> - */ - -#ifndef DBUS_UTILS_H -#define DBUS_UTILS_H - -char * -get_escaped_dbus_path (const char *prefix, - const char *component); - -#endif /* DBUS_UTILS_H */ diff --git a/src/backends/native/gen-default-modes.py b/src/backends/native/gen-default-modes.py deleted file mode 100755 index fed514d45..000000000 --- a/src/backends/native/gen-default-modes.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (C) 2016 Red Hat Inc. -# -# 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. - -import os -import sys - -if len(sys.argv) != 2: - print("Usage: %s [output file]"%sys.argv[0]) - exit(1) - -common_resolutions = [ - # 4:3 - (800, 600), - (1024, 768), - (1152, 864), - (1280, 960), - (1400, 1050), - (1440, 1080), - (1600, 1200), - (1920, 1440), - (2048, 1536), - # 16:10 - (1280, 800), - (1440, 900), - (1680, 1050), - (1920, 1200), - (2560, 1600), - # 16:9 - (1280, 720), - (1366, 768), - (1600, 900), - (1920, 1080), - (2048, 1152), - (2560, 1440), - (2880, 1620), - (3200, 1800), - (3840, 2160), - (4096, 2304), - (5120, 2880), -] - -output_lines = [ - "/* Generated by gen-default-modes.py */\n", - "static const drmModeModeInfo meta_default_landscape_drm_mode_infos[] = {", -] - -def sync_flags(hsync, vsync): - flags = "DRM_MODE_FLAG_" - flags += "NHSYNC" if hsync[0] == '-' else "PHSYNC" - flags += " | DRM_MODE_FLAG_" - flags += "NVSYNC" if vsync[0] == '-' else "PVSYNC" - return flags - -def drm_mode_info_from_modeline(line): - sline = line.split() - return "{ %d, %d, %d, %d, %d, 0, %d, %d, %d, %d, 0, 0, %s, DRM_MODE_TYPE_DEFAULT, %s }," % \ - (int(float(sline[2]) * 1000), - int(sline[3]), - int(sline[4]), - int(sline[5]), - int(sline[6]), - int(sline[7]), - int(sline[8]), - int(sline[9]), - int(sline[10]), - sync_flags(sline[11], sline[12]), - sline[1]) - -def portrait_drm_mode_info_from_modeline(line): - sline = line.split() - return "{ %d, %d, %d, %d, %d, 0, %d, %d, %d, %d, 0, 0, %s, DRM_MODE_TYPE_DEFAULT, \"%dx%d_60.00\" }," % \ - (int(float(sline[2]) * 1000), - int(sline[7]), - int(sline[8]), - int(sline[9]), - int(sline[10]), - int(sline[3]), - int(sline[4]), - int(sline[5]), - int(sline[6]), - sync_flags(sline[12], sline[11]), - int(sline[7]), int(sline[3])) - -for resolution in common_resolutions: - cvt = os.popen("%s %s %s" % ('cvt', resolution[0], resolution[1])) - cvt.readline() # discard comment line - line = cvt.readline() - output_lines.append(drm_mode_info_from_modeline(line)) - cvt.close() -output_lines.append("};") - -output_lines.append("") -output_lines.append("static const drmModeModeInfo meta_default_portrait_drm_mode_infos[] = {") -for resolution in common_resolutions: - cvt = os.popen("%s %s %s" % ('cvt', resolution[0], resolution[1])) - cvt.readline() # discard comment line - line = cvt.readline() - output_lines.append(portrait_drm_mode_info_from_modeline(line)) - cvt.close() -output_lines.append("};") - -try: - output_file = open(sys.argv[1], 'w') - - for line in output_lines: - output_file.write(line + "\n") - output_file.flush() - output_file.close() -except: - print("Failed to generate modelines:", sys.exc_info()[0]) - exit(1) diff --git a/src/backends/native/meta-backend-native-private.h b/src/backends/native/meta-backend-native-private.h deleted file mode 100644 index cd184685f..000000000 --- a/src/backends/native/meta-backend-native-private.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 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: - * Jonas Ådahl <jadahl@gmail.com> - */ - -#ifndef META_BACKEND_NATIVE_PRIVATE_H -#define META_BACKEND_NATIVE_PRIVATE_H - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-barrier-native.h" - -MetaBarrierManagerNative *meta_backend_native_get_barrier_manager (MetaBackendNative *native); - -MetaDevicePool * meta_backend_native_get_device_pool (MetaBackendNative *native); - -#endif /* META_BACKEND_NATIVE_PRIVATE_H */ diff --git a/src/backends/native/meta-backend-native-types.h b/src/backends/native/meta-backend-native-types.h deleted file mode 100644 index 152b57cf6..000000000 --- a/src/backends/native/meta-backend-native-types.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2019 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. - * - */ - -#ifndef META_BACKEND_NATIVE_TYPES_H -#define META_BACKEND_NATIVE_TYPES_H - -typedef struct _MetaBackendNative MetaBackendNative; -typedef struct _MetaSeatNative MetaSeatNative; -typedef struct _MetaSeatImpl MetaSeatImpl; -typedef struct _MetaKeymapNative MetaKeymapNative; -typedef struct _MetaRendererNative MetaRendererNative; -typedef struct _MetaGpuKms MetaGpuKms; -typedef struct _MetaCrtcVirtual MetaCrtcVirtual; -typedef struct _MetaCrtcModeVirtual MetaCrtcModeVirtual; -typedef struct _MetaDevicePool MetaDevicePool; -typedef struct _MetaDeviceFile MetaDeviceFile; - -typedef enum _MetaSeatNativeFlag -{ - META_SEAT_NATIVE_FLAG_NONE = 0, - META_SEAT_NATIVE_FLAG_NO_LIBINPUT = 1 << 0, -} MetaSeatNativeFlag; - -#endif /* META_BACKEND_NATIVE_TYPES_H */ diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c deleted file mode 100644 index 81d9629d0..000000000 --- a/src/backends/native/meta-backend-native.c +++ /dev/null @@ -1,768 +0,0 @@ -/* -*- 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 <jstpierre@mecheye.net> - */ - -/** - * SECTION:meta-backend-native - * @title: MetaBackendNative - * @short_description: A native (KMS/evdev) MetaBackend - * - * MetaBackendNative is an implementation of #MetaBackend that uses "native" - * technologies like DRM/KMS and libinput/evdev to perform the necessary - * functions. - */ - -#include "config.h" - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-input-thread.h" - -#include <sched.h> -#include <stdlib.h> - -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-idle-manager.h" -#include "backends/meta-keymap-utils.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-pointer-constraint.h" -#include "backends/meta-settings-private.h" -#include "backends/meta-stage-private.h" -#include "backends/native/meta-clutter-backend-native.h" -#include "backends/native/meta-device-pool-private.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-launcher.h" -#include "backends/native/meta-monitor-manager-native.h" -#include "backends/native/meta-renderer-native.h" -#include "backends/native/meta-seat-native.h" -#include "backends/native/meta-stage-native.h" -#include "cogl/cogl.h" -#include "core/meta-border.h" -#include "meta/main.h" - -#ifdef HAVE_REMOTE_DESKTOP -#include "backends/meta-screen-cast.h" -#endif - -enum -{ - PROP_0, - - PROP_HEADLESS, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -struct _MetaBackendNative -{ - MetaBackend parent; - - MetaLauncher *launcher; - MetaDevicePool *device_pool; - MetaUdev *udev; - MetaKms *kms; - - gboolean is_headless; - - gulong udev_device_added_handler_id; -}; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *initable_iface); - -G_DEFINE_TYPE_WITH_CODE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static void -disconnect_udev_device_added_handler (MetaBackendNative *native); - -static void -meta_backend_native_dispose (GObject *object) -{ - MetaBackendNative *native = META_BACKEND_NATIVE (object); - - if (native->udev_device_added_handler_id) - { - disconnect_udev_device_added_handler (native); - native->udev_device_added_handler_id = 0; - } - - if (native->kms) - meta_kms_prepare_shutdown (native->kms); - - G_OBJECT_CLASS (meta_backend_native_parent_class)->dispose (object); - - g_clear_object (&native->kms); - g_clear_object (&native->udev); - g_clear_object (&native->device_pool); - g_clear_pointer (&native->launcher, meta_launcher_free); -} - -static ClutterBackend * -meta_backend_native_create_clutter_backend (MetaBackend *backend) -{ - return g_object_new (META_TYPE_CLUTTER_BACKEND_NATIVE, NULL); -} - -static ClutterSeat * -meta_backend_native_create_default_seat (MetaBackend *backend, - GError **error) -{ - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - const char *seat_id; - MetaSeatNativeFlag flags; - - seat_id = meta_backend_native_get_seat_id (backend_native); - - if (meta_backend_native_is_headless (backend_native)) - flags = META_SEAT_NATIVE_FLAG_NO_LIBINPUT; - else - flags = META_SEAT_NATIVE_FLAG_NONE; - - return CLUTTER_SEAT (g_object_new (META_TYPE_SEAT_NATIVE, - "backend", backend, - "seat-id", seat_id, - "flags", flags, - NULL)); -} - -#ifdef HAVE_REMOTE_DESKTOP -static void -maybe_disable_screen_cast_dma_bufs (MetaBackendNative *native) -{ - MetaBackend *backend = META_BACKEND (native); - MetaSettings *settings = meta_backend_get_settings (backend); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - MetaScreenCast *screen_cast = meta_backend_get_screen_cast (backend); - MetaGpuKms *primary_gpu; - MetaKmsDevice *kms_device; - const char *driver_name; - static const char *enable_dma_buf_drivers[] = { - "i915", - NULL, - }; - - primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); - if (!primary_gpu) - { - g_message ("Disabling DMA buffer screen sharing (surfaceless)"); - goto disable_dma_bufs; - } - - kms_device = meta_gpu_kms_get_kms_device (primary_gpu); - driver_name = meta_kms_device_get_driver_name (kms_device); - - if (g_strv_contains (enable_dma_buf_drivers, driver_name)) - return; - - if (meta_settings_is_experimental_feature_enabled (settings, - META_EXPERIMENTAL_FEATURE_DMA_BUF_SCREEN_SHARING)) - return; - - g_message ("Disabling DMA buffer screen sharing for driver '%s'.", - driver_name); - -disable_dma_bufs: - meta_screen_cast_disable_dma_bufs (screen_cast); -} -#endif /* HAVE_REMOTE_DESKTOP */ - -static void -update_viewports (MetaBackend *backend) -{ - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - MetaSeatNative *seat = - META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend)); - MetaViewportInfo *viewports; - - viewports = meta_monitor_manager_get_viewports (monitor_manager); - meta_seat_native_set_viewports (seat, viewports); - g_object_unref (viewports); -} - -static void -meta_backend_native_post_init (MetaBackend *backend) -{ - MetaSettings *settings = meta_backend_get_settings (backend); - - META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend); - - if (meta_settings_is_experimental_feature_enabled (settings, - META_EXPERIMENTAL_FEATURE_RT_SCHEDULER)) - { - int retval; - struct sched_param sp = { - .sched_priority = sched_get_priority_min (SCHED_RR) - }; - - retval = sched_setscheduler (0, SCHED_RR | SCHED_RESET_ON_FORK, &sp); - - if (retval != 0) - g_warning ("Failed to set RT scheduler: %m"); - } - -#ifdef HAVE_REMOTE_DESKTOP - maybe_disable_screen_cast_dma_bufs (META_BACKEND_NATIVE (backend)); -#endif - - update_viewports (backend); -} - -static MetaMonitorManager * -meta_backend_native_create_monitor_manager (MetaBackend *backend, - GError **error) -{ - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaMonitorManager *manager; - - manager = g_initable_new (META_TYPE_MONITOR_MANAGER_NATIVE, NULL, error, - "backend", backend, - "needs-outputs", !backend_native->is_headless, - NULL); - if (!manager) - return NULL; - - g_signal_connect_swapped (manager, "monitors-changed-internal", - G_CALLBACK (update_viewports), backend); - - return manager; -} - -static MetaCursorRenderer * -meta_backend_native_get_cursor_renderer (MetaBackend *backend, - ClutterInputDevice *device) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - MetaSeatNative *seat_native = - META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend)); - - return meta_seat_native_maybe_ensure_cursor_renderer (seat_native, device); -} - -static MetaRenderer * -meta_backend_native_create_renderer (MetaBackend *backend, - GError **error) -{ - MetaBackendNative *native = META_BACKEND_NATIVE (backend); - MetaRendererNative *renderer_native; - - renderer_native = meta_renderer_native_new (native, error); - if (!renderer_native) - return NULL; - - return META_RENDERER (renderer_native); -} - -static MetaInputSettings * -meta_backend_native_get_input_settings (MetaBackend *backend) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - MetaSeatNative *seat_native = - META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend)); - - return meta_seat_impl_get_input_settings (seat_native->impl); -} - -static MetaLogicalMonitor * -meta_backend_native_get_current_logical_monitor (MetaBackend *backend) -{ - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - graphene_point_t point; - - meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL); - return meta_monitor_manager_get_logical_monitor_at (monitor_manager, - point.x, point.y); -} - -static void -meta_backend_native_set_keymap (MetaBackend *backend, - const char *layouts, - const char *variants, - const char *options) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (clutter_backend); - meta_seat_native_set_keyboard_map (META_SEAT_NATIVE (seat), - layouts, variants, options); - - meta_backend_notify_keymap_changed (backend); -} - -static struct xkb_keymap * -meta_backend_native_get_keymap (MetaBackend *backend) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (clutter_backend); - return meta_seat_native_get_keyboard_map (META_SEAT_NATIVE (seat)); -} - -static xkb_layout_index_t -meta_backend_native_get_keymap_layout_group (MetaBackend *backend) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (clutter_backend); - return meta_seat_native_get_keyboard_layout_index (META_SEAT_NATIVE (seat)); -} - -static void -meta_backend_native_lock_layout_group (MetaBackend *backend, - guint idx) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - xkb_layout_index_t old_idx; - ClutterSeat *seat; - - old_idx = meta_backend_native_get_keymap_layout_group (backend); - if (old_idx == idx) - return; - - seat = clutter_backend_get_default_seat (clutter_backend); - meta_seat_native_set_keyboard_layout_index (META_SEAT_NATIVE (seat), idx); - meta_backend_notify_keymap_layout_group_changed (backend, idx); -} - -const char * -meta_backend_native_get_seat_id (MetaBackendNative *backend_native) -{ - if (backend_native->is_headless) - return "seat0"; - else - return meta_launcher_get_seat_id (backend_native->launcher); -} - -gboolean -meta_backend_native_is_headless (MetaBackendNative *backend_native) -{ - return backend_native->is_headless; -} - -static void -meta_backend_native_set_pointer_constraint (MetaBackend *backend, - MetaPointerConstraint *constraint) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend); - MetaPointerConstraintImpl *constraint_impl = NULL; - cairo_region_t *region; - - if (constraint) - { - region = meta_pointer_constraint_get_region (constraint); - constraint_impl = meta_pointer_constraint_impl_native_new (constraint, - region); - } - - meta_seat_native_set_pointer_constraint (META_SEAT_NATIVE (seat), - constraint_impl); -} - -static void -meta_backend_native_update_screen_size (MetaBackend *backend, - int width, int height) -{ - ClutterActor *stage = meta_backend_get_stage (backend); - ClutterStageWindow *stage_window = - _clutter_stage_get_window (CLUTTER_STAGE (stage)); - MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window); - - meta_stage_native_rebuild_views (stage_native); - - clutter_actor_set_size (stage, width, height); -} - -static MetaGpuKms * -create_gpu_from_udev_device (MetaBackendNative *native, - GUdevDevice *device, - GError **error) -{ - MetaKmsDeviceFlag flags = META_KMS_DEVICE_FLAG_NONE; - const char *device_path; - MetaKmsDevice *kms_device; - - if (meta_is_udev_device_platform_device (device)) - flags |= META_KMS_DEVICE_FLAG_PLATFORM_DEVICE; - - if (meta_is_udev_device_boot_vga (device)) - flags |= META_KMS_DEVICE_FLAG_BOOT_VGA; - - if (meta_is_udev_device_disable_modifiers (device)) - flags |= META_KMS_DEVICE_FLAG_DISABLE_MODIFIERS; - - if (meta_is_udev_device_preferred_primary (device)) - flags |= META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY; - - device_path = g_udev_device_get_device_file (device); - - kms_device = meta_kms_create_device (native->kms, device_path, flags, - error); - if (!kms_device) - return NULL; - - return meta_gpu_kms_new (native, kms_device, error); -} - -static void -on_udev_device_added (MetaUdev *udev, - GUdevDevice *device, - MetaBackendNative *native) -{ - MetaBackend *backend = META_BACKEND (native); - g_autoptr (GError) error = NULL; - const char *device_path; - MetaGpuKms *new_gpu_kms; - GList *gpus, *l; - - if (!meta_udev_is_drm_device (udev, device)) - return; - - device_path = g_udev_device_get_device_file (device); - - gpus = meta_backend_get_gpus (backend); - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - - if (!g_strcmp0 (device_path, meta_gpu_kms_get_file_path (gpu_kms))) - { - g_warning ("Failed to hotplug secondary gpu '%s': %s", - device_path, "device already present"); - return; - } - } - - if (meta_is_udev_device_ignore (device)) - { - g_message ("Ignoring DRM device '%s' (from udev rule)", device_path); - return; - } - - new_gpu_kms = create_gpu_from_udev_device (native, device, &error); - if (!new_gpu_kms) - { - g_warning ("Failed to hotplug secondary gpu '%s': %s", - device_path, error->message); - return; - } - - meta_backend_add_gpu (backend, META_GPU (new_gpu_kms)); -} - -static void -connect_udev_device_added_handler (MetaBackendNative *native) -{ - native->udev_device_added_handler_id = - g_signal_connect (native->udev, "device-added", - G_CALLBACK (on_udev_device_added), native); -} - -static void -disconnect_udev_device_added_handler (MetaBackendNative *native) -{ - g_clear_signal_handler (&native->udev_device_added_handler_id, native->udev); -} - -static gboolean -init_gpus (MetaBackendNative *native, - GError **error) -{ - MetaBackend *backend = META_BACKEND (native); - MetaUdev *udev = meta_backend_native_get_udev (native); - GList *devices; - GList *l; - - devices = meta_udev_list_drm_devices (udev, error); - if (*error) - return FALSE; - - for (l = devices; l; l = l->next) - { - GUdevDevice *device = l->data; - MetaGpuKms *gpu_kms; - GError *local_error = NULL; - - if (meta_is_udev_device_ignore (device)) - { - g_message ("Ignoring DRM device '%s' (from udev rule)", - g_udev_device_get_device_file (device)); - continue; - } - - gpu_kms = create_gpu_from_udev_device (native, device, &local_error); - - if (!gpu_kms) - { - g_warning ("Failed to open gpu '%s': %s", - g_udev_device_get_device_file (device), - local_error->message); - g_clear_error (&local_error); - continue; - } - - meta_backend_add_gpu (backend, META_GPU (gpu_kms)); - } - - g_list_free_full (devices, g_object_unref); - - if (!native->is_headless && - g_list_length (meta_backend_get_gpus (backend)) == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "No GPUs found"); - return FALSE; - } - - connect_udev_device_added_handler (native); - - return TRUE; -} - -static gboolean -meta_backend_native_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaBackendNative *native = META_BACKEND_NATIVE (initable); - MetaKmsFlags kms_flags; - - if (!meta_is_stage_views_enabled ()) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "The native backend requires stage views"); - return FALSE; - } - - if (!native->is_headless) - { - native->launcher = meta_launcher_new (error); - if (!native->launcher) - return FALSE; - } - - native->device_pool = meta_device_pool_new (native->launcher); - native->udev = meta_udev_new (native); - - kms_flags = META_KMS_FLAG_NONE; - if (native->is_headless) - kms_flags |= META_KMS_FLAG_NO_MODE_SETTING; - - native->kms = meta_kms_new (META_BACKEND (native), kms_flags, error); - if (!native->kms) - return FALSE; - - if (!init_gpus (native, error)) - return FALSE; - - return initable_parent_iface->init (initable, cancellable, error); -} - -static void -meta_backend_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaBackendNative *backend_native = META_BACKEND_NATIVE (object); - - switch (prop_id) - { - case PROP_HEADLESS: - backend_native->is_headless = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -initable_iface_init (GInitableIface *initable_iface) -{ - initable_parent_iface = g_type_interface_peek_parent (initable_iface); - - initable_iface->init = meta_backend_native_initable_init; -} - -static void -meta_backend_native_class_init (MetaBackendNativeClass *klass) -{ - MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_backend_native_set_property; - object_class->dispose = meta_backend_native_dispose; - - backend_class->create_clutter_backend = meta_backend_native_create_clutter_backend; - backend_class->create_default_seat = meta_backend_native_create_default_seat; - - backend_class->post_init = meta_backend_native_post_init; - - backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager; - backend_class->get_cursor_renderer = meta_backend_native_get_cursor_renderer; - backend_class->create_renderer = meta_backend_native_create_renderer; - backend_class->get_input_settings = meta_backend_native_get_input_settings; - - backend_class->get_current_logical_monitor = meta_backend_native_get_current_logical_monitor; - - backend_class->set_keymap = meta_backend_native_set_keymap; - backend_class->get_keymap = meta_backend_native_get_keymap; - backend_class->get_keymap_layout_group = meta_backend_native_get_keymap_layout_group; - backend_class->lock_layout_group = meta_backend_native_lock_layout_group; - backend_class->update_screen_size = meta_backend_native_update_screen_size; - - backend_class->set_pointer_constraint = meta_backend_native_set_pointer_constraint; - - obj_props[PROP_HEADLESS] = - g_param_spec_boolean ("headless", - "headless", - "Headless", - FALSE, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} - -static void -meta_backend_native_init (MetaBackendNative *native) -{ -} - -MetaLauncher * -meta_backend_native_get_launcher (MetaBackendNative *native) -{ - return native->launcher; -} - -MetaDevicePool * -meta_backend_native_get_device_pool (MetaBackendNative *native) -{ - return native->device_pool; -} - -MetaUdev * -meta_backend_native_get_udev (MetaBackendNative *native) -{ - return native->udev; -} - -MetaKms * -meta_backend_native_get_kms (MetaBackendNative *native) -{ - return native->kms; -} - -gboolean -meta_activate_vt (int vt, GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaBackendNative *native = META_BACKEND_NATIVE (backend); - MetaLauncher *launcher = meta_backend_native_get_launcher (native); - - if (native->is_headless) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Can't switch VT while headless"); - return FALSE; - } - - return meta_launcher_activate_vt (launcher, vt, error); -} - -void -meta_backend_native_pause (MetaBackendNative *native) -{ - MetaBackend *backend = META_BACKEND (native); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerNative *monitor_manager_native = - META_MONITOR_MANAGER_NATIVE (monitor_manager); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - MetaSeatNative *seat = - META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend)); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - COGL_TRACE_BEGIN_SCOPED (MetaBackendNativePause, - "Backend (pause)"); - - meta_seat_native_release_devices (seat); - meta_renderer_pause (renderer); - - disconnect_udev_device_added_handler (native); - - meta_monitor_manager_native_pause (monitor_manager_native); -} - -void meta_backend_native_resume (MetaBackendNative *native) -{ - MetaBackend *backend = META_BACKEND (native); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerNative *monitor_manager_native = - META_MONITOR_MANAGER_NATIVE (monitor_manager); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - MetaSeatNative *seat = - META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend)); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaIdleManager *idle_manager; - MetaInputSettings *input_settings; - - COGL_TRACE_BEGIN_SCOPED (MetaBackendNativeResume, - "Backend (resume)"); - - meta_monitor_manager_native_resume (monitor_manager_native); - meta_kms_resume (native->kms); - - connect_udev_device_added_handler (native); - - meta_seat_native_reclaim_devices (seat); - meta_renderer_resume (renderer); - - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - - idle_manager = meta_backend_get_idle_manager (backend); - meta_idle_manager_reset_idle_time (idle_manager); - - input_settings = meta_backend_get_input_settings (backend); - meta_input_settings_maybe_restore_numlock_state (input_settings); - - clutter_seat_ensure_a11y_state (CLUTTER_SEAT (seat)); -} diff --git a/src/backends/native/meta-backend-native.h b/src/backends/native/meta-backend-native.h deleted file mode 100644 index aad4c8413..000000000 --- a/src/backends/native/meta-backend-native.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- 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 <jstpierre@mecheye.net> - */ - -#ifndef META_BACKEND_NATIVE_H -#define META_BACKEND_NATIVE_H - -#include "backends/meta-backend-private.h" -#include "backends/native/meta-clutter-backend-native.h" -#include "backends/native/meta-kms-types.h" -#include "backends/native/meta-launcher.h" -#include "backends/native/meta-udev.h" - -#define META_TYPE_BACKEND_NATIVE (meta_backend_native_get_type ()) -META_EXPORT_TEST -G_DECLARE_FINAL_TYPE (MetaBackendNative, meta_backend_native, - META, BACKEND_NATIVE, MetaBackend) - -gboolean meta_activate_vt (int vt, GError **error); - -void meta_backend_native_pause (MetaBackendNative *backend_native); - -void meta_backend_native_resume (MetaBackendNative *backend_native); - -MetaLauncher * meta_backend_native_get_launcher (MetaBackendNative *native); - -MetaUdev * meta_backend_native_get_udev (MetaBackendNative *native); - -MetaKms * meta_backend_native_get_kms (MetaBackendNative *native); - -const char * meta_backend_native_get_seat_id (MetaBackendNative *backend_native); - -gboolean meta_backend_native_is_headless (MetaBackendNative *backend_native); - -#endif /* META_BACKEND_NATIVE_H */ diff --git a/src/backends/native/meta-barrier-native.c b/src/backends/native/meta-barrier-native.c deleted file mode 100644 index 3c9c1eabe..000000000 --- a/src/backends/native/meta-barrier-native.c +++ /dev/null @@ -1,652 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 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: - * Jonas Ådahl <jadahl@gmail.com> - */ - -/** - * SECTION:barrier-native - * @Title: MetaBarrierImplNative - * @Short_Description: Pointer barriers implementation for the native backend - */ - -#include "config.h" - -#include "backends/native/meta-barrier-native.h" - -#include <stdlib.h> - -#include "backends/meta-backend-private.h" -#include "backends/meta-barrier-private.h" -#include "backends/native/meta-seat-native.h" -#include "meta/barrier.h" -#include "meta/util.h" - -struct _MetaBarrierManagerNative -{ - GHashTable *barriers; - GMutex mutex; -}; - -typedef enum -{ - /* The barrier is active and responsive to pointer motion. */ - META_BARRIER_STATE_ACTIVE, - - /* An intermediate state after a pointer hit the pointer barrier. */ - META_BARRIER_STATE_HIT, - - /* The barrier was hit by a pointer and is still within the hit box and - * has not been released.*/ - META_BARRIER_STATE_HELD, - - /* The pointer was released by the user. If the following motion hits - * the barrier, it will pass through. */ - META_BARRIER_STATE_RELEASE, - - /* An intermediate state when the pointer has left the barrier. */ - META_BARRIER_STATE_LEFT, -} MetaBarrierState; - -struct _MetaBarrierImplNative -{ - MetaBarrierImpl parent; - - MetaBarrier *barrier; - MetaBarrierManagerNative *manager; - - gboolean is_active; - MetaBarrierState state; - int trigger_serial; - guint32 last_event_time; - MetaBarrierDirection blocked_dir; - GMainContext *main_context; -}; - -G_DEFINE_TYPE (MetaBarrierImplNative, - meta_barrier_impl_native, - META_TYPE_BARRIER_IMPL) - -static int -next_serial (void) -{ - static int barrier_serial = 1; - - barrier_serial++; - - /* If it wraps, avoid 0 as it's not a valid serial. */ - if (barrier_serial == 0) - barrier_serial++; - - return barrier_serial; -} - -static gboolean -is_barrier_horizontal (MetaBarrier *barrier) -{ - return meta_border_is_horizontal (&barrier->priv->border); -} - -static gboolean -is_barrier_blocking_directions (MetaBarrier *barrier, - MetaBarrierDirection directions) -{ - return meta_border_is_blocking_directions (&barrier->priv->border, - directions); -} - -static void -dismiss_pointer (MetaBarrierImplNative *self) -{ - self->state = META_BARRIER_STATE_LEFT; -} - -/* - * Calculate the hit box for a held motion. The hit box is a 2 px wide region - * in the opposite direction of every direction the barrier blocks. The purpose - * of this is to allow small movements without receiving a "left" signal. This - * heuristic comes from the X.org pointer barrier implementation. - */ -static MetaLine2 -calculate_barrier_hit_box (MetaBarrier *barrier) -{ - MetaLine2 hit_box = barrier->priv->border.line; - - if (is_barrier_horizontal (barrier)) - { - if (is_barrier_blocking_directions (barrier, - META_BARRIER_DIRECTION_POSITIVE_Y)) - hit_box.a.y -= 2.0f; - if (is_barrier_blocking_directions (barrier, - META_BARRIER_DIRECTION_NEGATIVE_Y)) - hit_box.b.y += 2.0f; - } - else - { - if (is_barrier_blocking_directions (barrier, - META_BARRIER_DIRECTION_POSITIVE_X)) - hit_box.a.x -= 2.0f; - if (is_barrier_blocking_directions (barrier, - META_BARRIER_DIRECTION_NEGATIVE_X)) - hit_box.b.x += 2.0f; - } - - return hit_box; -} - -static gboolean -is_within_box (MetaLine2 box, - MetaVector2 point) -{ - return (point.x >= box.a.x && point.x < box.b.x && - point.y >= box.a.y && point.y < box.b.y); -} - -static void -maybe_release_barrier (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaBarrierImplNative *self = key; - MetaBarrier *barrier = self->barrier; - MetaLine2 *motion = user_data; - MetaLine2 hit_box; - - if (self->state != META_BARRIER_STATE_HELD) - return; - - /* Release if we end up outside barrier end points. */ - if (is_barrier_horizontal (barrier)) - { - if (motion->b.x > MAX (barrier->priv->border.line.a.x, - barrier->priv->border.line.b.x) || - motion->b.x < MIN (barrier->priv->border.line.a.x, - barrier->priv->border.line.b.x)) - { - dismiss_pointer (self); - return; - } - } - else - { - if (motion->b.y > MAX (barrier->priv->border.line.a.y, - barrier->priv->border.line.b.y) || - motion->b.y < MIN (barrier->priv->border.line.a.y, - barrier->priv->border.line.b.y)) - { - dismiss_pointer (self); - return; - } - } - - /* Release if we don't intersect and end up outside of hit box. */ - hit_box = calculate_barrier_hit_box (barrier); - if (!is_within_box (hit_box, motion->b)) - { - dismiss_pointer (self); - return; - } -} - -static void -maybe_release_barriers (MetaBarrierManagerNative *manager, - float prev_x, - float prev_y, - float x, - float y) -{ - MetaLine2 motion = { - .a = { - .x = prev_x, - .y = prev_y, - }, - .b = { - .x = x, - .y = y, - }, - }; - - g_hash_table_foreach (manager->barriers, - maybe_release_barrier, - &motion); -} - -typedef struct _MetaClosestBarrierData -{ - struct - { - MetaLine2 motion; - MetaBarrierDirection directions; - } in; - - struct - { - float closest_distance_2; - MetaBarrierImplNative *barrier_impl; - } out; -} MetaClosestBarrierData; - -static void -update_closest_barrier (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaBarrierImplNative *self = key; - MetaBarrier *barrier = self->barrier; - MetaClosestBarrierData *data = user_data; - MetaVector2 intersection; - float dx, dy; - float distance_2; - - /* Ignore if the barrier is not blocking in any of the motions directions. */ - if (!is_barrier_blocking_directions (barrier, data->in.directions)) - return; - - /* Ignore if the barrier released the pointer. */ - if (self->state == META_BARRIER_STATE_RELEASE) - return; - - /* Ignore if we are moving away from barrier. */ - if (self->state == META_BARRIER_STATE_HELD && - (data->in.directions & self->blocked_dir) == 0) - return; - - /* Check if the motion intersects with the barrier, and retrieve the - * intersection point if any. */ - if (!meta_line2_intersects_with (&barrier->priv->border.line, - &data->in.motion, - &intersection)) - return; - - /* Calculate the distance to the barrier and keep track of the closest - * barrier. */ - dx = intersection.x - data->in.motion.a.x; - dy = intersection.y - data->in.motion.a.y; - distance_2 = dx*dx + dy*dy; - if (data->out.barrier_impl == NULL || - distance_2 < data->out.closest_distance_2) - { - data->out.barrier_impl = self; - data->out.closest_distance_2 = distance_2; - } -} - -static gboolean -get_closest_barrier (MetaBarrierManagerNative *manager, - float prev_x, - float prev_y, - float x, - float y, - MetaBarrierDirection motion_dir, - MetaBarrierImplNative **barrier_impl) -{ - MetaClosestBarrierData closest_barrier_data; - - closest_barrier_data = (MetaClosestBarrierData) { - .in = { - .motion = { - .a = { - .x = prev_x, - .y = prev_y, - }, - .b = { - .x = x, - .y = y, - }, - }, - .directions = motion_dir, - }, - }; - - g_hash_table_foreach (manager->barriers, - update_closest_barrier, - &closest_barrier_data); - - if (closest_barrier_data.out.barrier_impl != NULL) - { - *barrier_impl = closest_barrier_data.out.barrier_impl; - return TRUE; - } - else - { - return FALSE; - } -} - -typedef struct _MetaBarrierEventData -{ - guint32 time; - float prev_x; - float prev_y; - float x; - float y; - float dx; - float dy; -} MetaBarrierEventData; - -typedef struct -{ - MetaBarrierEvent *event; - MetaBarrier *barrier; - MetaBarrierState state; -} MetaBarrierIdleData; - -static gboolean -emit_event_idle (MetaBarrierIdleData *idle_data) -{ - if (idle_data->state == META_BARRIER_STATE_HELD) - _meta_barrier_emit_hit_signal (idle_data->barrier, idle_data->event); - else - _meta_barrier_emit_left_signal (idle_data->barrier, idle_data->event); - - meta_barrier_event_unref (idle_data->event); - - return G_SOURCE_REMOVE; -} - -static void -queue_event (MetaBarrierImplNative *self, - MetaBarrierEvent *event) -{ - MetaBarrierIdleData *idle_data; - GSource *source; - - idle_data = g_new0 (MetaBarrierIdleData, 1); - idle_data->state = self->state; - idle_data->barrier = self->barrier; - idle_data->event = event; - - source = g_idle_source_new (); - g_source_set_priority (source, G_PRIORITY_HIGH); - g_source_set_callback (source, - (GSourceFunc) emit_event_idle, - idle_data, - g_free); - - g_source_attach (source, self->main_context); - g_source_unref (source); -} - -static void -emit_barrier_event (MetaBarrierImplNative *self, - guint32 time, - float prev_x, - float prev_y, - float x, - float y, - float dx, - float dy) -{ - MetaBarrierEvent *event = g_new0 (MetaBarrierEvent, 1); - MetaBarrierState old_state = self->state; - - switch (self->state) - { - case META_BARRIER_STATE_HIT: - self->state = META_BARRIER_STATE_HELD; - self->trigger_serial = next_serial (); - event->dt = 0; - - break; - case META_BARRIER_STATE_RELEASE: - case META_BARRIER_STATE_LEFT: - self->state = META_BARRIER_STATE_ACTIVE; - - G_GNUC_FALLTHROUGH; - case META_BARRIER_STATE_HELD: - event->dt = time - self->last_event_time; - - break; - case META_BARRIER_STATE_ACTIVE: - g_assert_not_reached (); /* Invalid state. */ - } - - event->ref_count = 1; - event->event_id = self->trigger_serial; - event->time = time; - - event->x = x; - event->y = y; - event->dx = dx; - event->dy = dy; - - event->grabbed = self->state == META_BARRIER_STATE_HELD; - event->released = old_state == META_BARRIER_STATE_RELEASE; - - self->last_event_time = time; - - queue_event (self, event); -} - -static void -maybe_emit_barrier_event (gpointer key, gpointer value, gpointer user_data) -{ - MetaBarrierImplNative *self = key; - MetaBarrierEventData *data = user_data; - - switch (self->state) - { - case META_BARRIER_STATE_ACTIVE: - break; - case META_BARRIER_STATE_HIT: - case META_BARRIER_STATE_HELD: - case META_BARRIER_STATE_RELEASE: - case META_BARRIER_STATE_LEFT: - emit_barrier_event (self, - data->time, - data->prev_x, - data->prev_y, - data->x, - data->y, - data->dx, - data->dy); - break; - } -} - -/* Clamp (x, y) to the barrier and remove clamped direction from motion_dir. */ -static void -clamp_to_barrier (MetaBarrierImplNative *self, - MetaBarrierDirection *motion_dir, - float *x, - float *y) -{ - MetaBarrier *barrier = self->barrier; - - if (is_barrier_horizontal (barrier)) - { - if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_Y) - *y = barrier->priv->border.line.a.y; - else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_Y) - *y = barrier->priv->border.line.a.y; - - self->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_Y | - META_BARRIER_DIRECTION_NEGATIVE_Y); - *motion_dir &= ~(META_BARRIER_DIRECTION_POSITIVE_Y | - META_BARRIER_DIRECTION_NEGATIVE_Y); - } - else - { - if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_X) - *x = barrier->priv->border.line.a.x; - else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_X) - *x = barrier->priv->border.line.a.x; - - self->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_X | - META_BARRIER_DIRECTION_NEGATIVE_X); - *motion_dir &= ~(META_BARRIER_DIRECTION_POSITIVE_X | - META_BARRIER_DIRECTION_NEGATIVE_X); - } - - self->state = META_BARRIER_STATE_HIT; -} - -void -meta_barrier_manager_native_process_in_impl (MetaBarrierManagerNative *manager, - ClutterInputDevice *device, - guint32 time, - float *x, - float *y) -{ - graphene_point_t prev_pos; - float prev_x; - float prev_y; - float orig_x = *x; - float orig_y = *y; - MetaBarrierDirection motion_dir = 0; - MetaBarrierEventData barrier_event_data; - MetaBarrierImplNative *barrier_impl; - - if (!clutter_seat_query_state (clutter_input_device_get_seat (device), - device, NULL, &prev_pos, NULL)) - return; - - g_mutex_lock (&manager->mutex); - - prev_x = prev_pos.x; - prev_y = prev_pos.y; - - /* Get the direction of the motion vector. */ - if (prev_x < *x) - motion_dir |= META_BARRIER_DIRECTION_POSITIVE_X; - else if (prev_x > *x) - motion_dir |= META_BARRIER_DIRECTION_NEGATIVE_X; - if (prev_y < *y) - motion_dir |= META_BARRIER_DIRECTION_POSITIVE_Y; - else if (prev_y > *y) - motion_dir |= META_BARRIER_DIRECTION_NEGATIVE_Y; - - /* Clamp to the closest barrier in any direction until either there are no - * more barriers to clamp to or all directions have been clamped. */ - while (motion_dir != 0) - { - if (get_closest_barrier (manager, - prev_x, prev_y, - *x, *y, - motion_dir, - &barrier_impl)) - clamp_to_barrier (barrier_impl, &motion_dir, x, y); - else - break; - } - - /* Potentially release active barrier movements. */ - maybe_release_barriers (manager, prev_x, prev_y, *x, *y); - - /* Initiate or continue barrier interaction. */ - barrier_event_data = (MetaBarrierEventData) { - .time = time, - .prev_x = prev_x, - .prev_y = prev_y, - .x = *x, - .y = *y, - .dx = orig_x - prev_x, - .dy = orig_y - prev_y, - }; - - g_hash_table_foreach (manager->barriers, - maybe_emit_barrier_event, - &barrier_event_data); - - g_mutex_unlock (&manager->mutex); -} - -static gboolean -_meta_barrier_impl_native_is_active (MetaBarrierImpl *impl) -{ - MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl); - - return self->is_active; -} - -static void -_meta_barrier_impl_native_release (MetaBarrierImpl *impl, - MetaBarrierEvent *event) -{ - MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl); - - if (self->state == META_BARRIER_STATE_HELD && - event->event_id == self->trigger_serial) - self->state = META_BARRIER_STATE_RELEASE; -} - -static void -_meta_barrier_impl_native_destroy (MetaBarrierImpl *impl) -{ - MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl); - - g_mutex_lock (&self->manager->mutex); - g_hash_table_remove (self->manager->barriers, self); - g_mutex_unlock (&self->manager->mutex); - g_main_context_unref (self->main_context); - self->is_active = FALSE; -} - -MetaBarrierImpl * -meta_barrier_impl_native_new (MetaBarrier *barrier) -{ - MetaBarrierImplNative *self; - MetaBarrierManagerNative *manager; - ClutterBackend *backend = clutter_get_default_backend (); - ClutterSeat *seat = clutter_backend_get_default_seat (backend); - - self = g_object_new (META_TYPE_BARRIER_IMPL_NATIVE, NULL); - - self->barrier = barrier; - self->is_active = TRUE; - self->main_context = g_main_context_ref_thread_default (); - - manager = meta_seat_native_get_barrier_manager (META_SEAT_NATIVE (seat)); - self->manager = manager; - g_mutex_lock (&manager->mutex); - g_hash_table_add (manager->barriers, self); - g_mutex_unlock (&manager->mutex); - - return META_BARRIER_IMPL (self); -} - -static void -meta_barrier_impl_native_class_init (MetaBarrierImplNativeClass *klass) -{ - MetaBarrierImplClass *impl_class = META_BARRIER_IMPL_CLASS (klass); - - impl_class->is_active = _meta_barrier_impl_native_is_active; - impl_class->release = _meta_barrier_impl_native_release; - impl_class->destroy = _meta_barrier_impl_native_destroy; -} - -static void -meta_barrier_impl_native_init (MetaBarrierImplNative *self) -{ -} - -MetaBarrierManagerNative * -meta_barrier_manager_native_new (void) -{ - MetaBarrierManagerNative *manager; - - manager = g_new0 (MetaBarrierManagerNative, 1); - - manager->barriers = g_hash_table_new (NULL, NULL); - g_mutex_init (&manager->mutex); - - return manager; -} diff --git a/src/backends/native/meta-barrier-native.h b/src/backends/native/meta-barrier-native.h deleted file mode 100644 index 1bcf56c7c..000000000 --- a/src/backends/native/meta-barrier-native.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 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: - * Jonas Ådahl <jadahl@gmail.com> - */ - -#ifndef META_BARRIER_NATIVE_H -#define META_BARRIER_NATIVE_H - -#include "backends/meta-barrier-private.h" - -G_BEGIN_DECLS - -#define META_TYPE_BARRIER_IMPL_NATIVE (meta_barrier_impl_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaBarrierImplNative, - meta_barrier_impl_native, - META, BARRIER_IMPL_NATIVE, - MetaBarrierImpl) - -typedef struct _MetaBarrierManagerNative MetaBarrierManagerNative; - - -MetaBarrierImpl *meta_barrier_impl_native_new (MetaBarrier *barrier); - -MetaBarrierManagerNative *meta_barrier_manager_native_new (void); -void meta_barrier_manager_native_process_in_impl (MetaBarrierManagerNative *manager, - ClutterInputDevice *device, - guint32 time, - float *x, - float *y); - -G_END_DECLS - -#endif /* META_BARRIER_NATIVE_H */ diff --git a/src/backends/native/meta-clutter-backend-native.c b/src/backends/native/meta-clutter-backend-native.c deleted file mode 100644 index a28ecea99..000000000 --- a/src/backends/native/meta-clutter-backend-native.c +++ /dev/null @@ -1,111 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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: - * Jonas Ådahl <jadahl@gmail.com> - */ - -/** - * SECTION:meta-clutter-backend-native - * @title: MetaClutterBackendNatve - * @short_description: A native backend which renders using EGL. - * - * MetaClutterBackendNative is the #ClutterBackend which is used by the native - * (as opposed to the X) backend. It creates a stage with #MetaStageNative and - * renders using the #CoglRenderer. - * - * Note that MetaClutterBackendNative is something different than a - * #MetaBackendNative. The former is a #ClutterBackend implementation, while - * the latter is a #MetaBackend implementation. - */ - -#include "config.h" - -#include "backends/native/meta-clutter-backend-native.h" - -#include <glib-object.h> - -#include "backends/meta-backend-private.h" -#include "backends/meta-renderer.h" -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-seat-native.h" -#include "backends/native/meta-stage-native.h" -#include "clutter/clutter.h" -#include "core/bell.h" -#include "meta/meta-backend.h" - -struct _MetaClutterBackendNative -{ - ClutterBackend parent; -}; - -G_DEFINE_TYPE (MetaClutterBackendNative, meta_clutter_backend_native, - CLUTTER_TYPE_BACKEND) - -static CoglRenderer * -meta_clutter_backend_native_get_renderer (ClutterBackend *clutter_backend, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - return meta_renderer_create_cogl_renderer (renderer); -} - -static ClutterStageWindow * -meta_clutter_backend_native_create_stage (ClutterBackend *clutter_backend, - ClutterStage *wrapper, - GError **error) -{ - return g_object_new (META_TYPE_STAGE_NATIVE, - "backend", clutter_backend, - "wrapper", wrapper, - NULL); -} - -static ClutterSeat * -meta_clutter_backend_native_get_default_seat (ClutterBackend *clutter_backend) -{ - MetaBackend *backend = meta_get_backend (); - - return meta_backend_get_default_seat (backend); -} - -static gboolean -meta_clutter_backend_native_is_display_server (ClutterBackend *clutter_backend) -{ - return TRUE; -} - -static void -meta_clutter_backend_native_init (MetaClutterBackendNative *clutter_backend_nativen) -{ -} - -static void -meta_clutter_backend_native_class_init (MetaClutterBackendNativeClass *klass) -{ - ClutterBackendClass *clutter_backend_class = CLUTTER_BACKEND_CLASS (klass); - - clutter_backend_class->get_renderer = meta_clutter_backend_native_get_renderer; - clutter_backend_class->create_stage = meta_clutter_backend_native_create_stage; - clutter_backend_class->get_default_seat = meta_clutter_backend_native_get_default_seat; - clutter_backend_class->is_display_server = meta_clutter_backend_native_is_display_server; -} diff --git a/src/backends/native/meta-clutter-backend-native.h b/src/backends/native/meta-clutter-backend-native.h deleted file mode 100644 index dea35988c..000000000 --- a/src/backends/native/meta-clutter-backend-native.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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: - * Jonas Ådahl <jadahl@gmail.com> - */ - -#ifndef META_CLUTTER_BACKEND_NATIVE_H -#define META_CLUTTER_BACKEND_NATIVE_H - -#include <glib-object.h> - -#include "backends/native/meta-stage-native.h" -#include "clutter/clutter.h" - -#define META_TYPE_CLUTTER_BACKEND_NATIVE (meta_clutter_backend_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaClutterBackendNative, meta_clutter_backend_native, - META, CLUTTER_BACKEND_NATIVE, - ClutterBackend) - -#endif /* META_CLUTTER_BACKEND_NATIVE_H */ diff --git a/src/backends/native/meta-cogl-utils.c b/src/backends/native/meta-cogl-utils.c deleted file mode 100644 index 582f86661..000000000 --- a/src/backends/native/meta-cogl-utils.c +++ /dev/null @@ -1,85 +0,0 @@ -/* meta-cogl-utils.c - * - * Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> - * - * 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. - * - * SPDX-License-Identifier: GPL-2.0-or-later - * - */ - -#include "backends/native/meta-cogl-utils.h" - -#include <drm_fourcc.h> - -typedef struct _PixelFormatMap { - uint32_t drm_format; - CoglPixelFormat cogl_format; - CoglTextureComponents cogl_components; -} PixelFormatMap; - -static const PixelFormatMap pixel_format_map[] = { -/* DRM formats are defined as little-endian, not machine endian. */ -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - { DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, -#elif G_BYTE_ORDER == G_BIG_ENDIAN - /* DRM_FORMAT_RGB565 cannot be expressed. */ - { DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, -#else -#error "unexpected G_BYTE_ORDER" -#endif -}; - -gboolean -meta_cogl_pixel_format_from_drm_format (uint32_t drm_format, - CoglPixelFormat *out_format, - CoglTextureComponents *out_components) -{ - const size_t n = G_N_ELEMENTS (pixel_format_map); - size_t i; - - for (i = 0; i < n; i++) - { - if (pixel_format_map[i].drm_format == drm_format) - break; - } - - if (i == n) - return FALSE; - - if (out_format) - *out_format = pixel_format_map[i].cogl_format; - - if (out_components) - *out_components = pixel_format_map[i].cogl_components; - - return TRUE; -} diff --git a/src/backends/native/meta-cogl-utils.h b/src/backends/native/meta-cogl-utils.h deleted file mode 100644 index b5fe6296f..000000000 --- a/src/backends/native/meta-cogl-utils.h +++ /dev/null @@ -1,38 +0,0 @@ -/* meta-cogl-utils.h - * - * Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> - * - * 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. - * - * SPDX-License-Identifier: GPL-2.0-or-later - * - */ - -#ifndef META_COGL_UTILS_H -#define META_COGL_UTILS_H - -#include "cogl/cogl.h" - -G_BEGIN_DECLS - -gboolean -meta_cogl_pixel_format_from_drm_format (uint32_t drm_format, - CoglPixelFormat *out_format, - CoglTextureComponents *out_components); - -G_END_DECLS - -#endif /* META_COGL_UTILS_H */ diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c deleted file mode 100644 index f1bc79146..000000000 --- a/src/backends/native/meta-crtc-kms.c +++ /dev/null @@ -1,386 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013-2017 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-crtc-kms.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/native/meta-crtc-mode-kms.h" -#include "backends/native/meta-gpu-kms.h" -#include "backends/native/meta-output-kms.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-mode.h" -#include "backends/native/meta-kms-plane.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-monitor-manager-native.h" - -#define ALL_TRANSFORMS_MASK ((1 << META_MONITOR_N_TRANSFORMS) - 1) - -struct _MetaCrtcKms -{ - MetaCrtcNative parent; - - MetaKmsCrtc *kms_crtc; - - MetaKmsPlane *primary_plane; - - gpointer cursor_renderer_private; - GDestroyNotify cursor_renderer_private_destroy_notify; - - gboolean is_gamma_valid; -}; - -static GQuark kms_crtc_crtc_kms_quark; - -G_DEFINE_TYPE (MetaCrtcKms, meta_crtc_kms, META_TYPE_CRTC_NATIVE) - -gpointer -meta_crtc_kms_get_cursor_renderer_private (MetaCrtcKms *crtc_kms) -{ - return crtc_kms->cursor_renderer_private; -} - -void -meta_crtc_kms_set_cursor_renderer_private (MetaCrtcKms *crtc_kms, - gpointer cursor_renderer_private, - GDestroyNotify destroy_notify) -{ - g_clear_pointer (&crtc_kms->cursor_renderer_private, - crtc_kms->cursor_renderer_private_destroy_notify); - - crtc_kms->cursor_renderer_private = cursor_renderer_private; - crtc_kms->cursor_renderer_private_destroy_notify = destroy_notify; -} - -static gboolean -is_transform_handled (MetaCrtcKms *crtc_kms, - MetaMonitorTransform transform) -{ - if (!crtc_kms->primary_plane) - return FALSE; - - return meta_kms_plane_is_transform_handled (crtc_kms->primary_plane, - transform); -} - -static gboolean -meta_crtc_kms_is_transform_handled (MetaCrtcNative *crtc_native, - MetaMonitorTransform transform) -{ - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc_native); - - return is_transform_handled (crtc_kms, transform); -} - -void -meta_crtc_kms_apply_transform (MetaCrtcKms *crtc_kms, - MetaKmsPlaneAssignment *kms_plane_assignment) -{ - MetaCrtc *crtc = META_CRTC (crtc_kms); - const MetaCrtcConfig *crtc_config; - MetaMonitorTransform hw_transform; - - crtc_config = meta_crtc_get_config (crtc); - - hw_transform = crtc_config->transform; - if (!is_transform_handled (crtc_kms, hw_transform)) - hw_transform = META_MONITOR_TRANSFORM_NORMAL; - if (!is_transform_handled (crtc_kms, hw_transform)) - return; - - meta_kms_plane_update_set_rotation (crtc_kms->primary_plane, - kms_plane_assignment, - hw_transform); -} - -void -meta_crtc_kms_assign_primary_plane (MetaCrtcKms *crtc_kms, - MetaDrmBuffer *buffer, - MetaKmsUpdate *kms_update) -{ - MetaCrtc *crtc = META_CRTC (crtc_kms); - const MetaCrtcConfig *crtc_config; - const MetaCrtcModeInfo *crtc_mode_info; - MetaFixed16Rectangle src_rect; - MetaRectangle dst_rect; - MetaKmsAssignPlaneFlag flags; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsPlane *primary_kms_plane; - MetaKmsPlaneAssignment *plane_assignment; - - crtc_config = meta_crtc_get_config (crtc); - crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); - - src_rect = (MetaFixed16Rectangle) { - .x = meta_fixed_16_from_int (0), - .y = meta_fixed_16_from_int (0), - .width = meta_fixed_16_from_int (crtc_mode_info->width), - .height = meta_fixed_16_from_int (crtc_mode_info->height), - }; - dst_rect = (MetaRectangle) { - .x = 0, - .y = 0, - .width = crtc_mode_info->width, - .height = crtc_mode_info->height, - }; - - flags = META_KMS_ASSIGN_PLANE_FLAG_NONE; - - kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - kms_device = meta_kms_crtc_get_device (kms_crtc); - primary_kms_plane = meta_kms_device_get_primary_plane_for (kms_device, - kms_crtc); - plane_assignment = meta_kms_update_assign_plane (kms_update, - kms_crtc, - primary_kms_plane, - buffer, - src_rect, - dst_rect, - flags); - meta_crtc_kms_apply_transform (crtc_kms, plane_assignment); -} - -static GList * -generate_crtc_connector_list (MetaGpu *gpu, - MetaCrtc *crtc) -{ - GList *connectors = NULL; - GList *l; - - for (l = meta_gpu_get_outputs (gpu); l; l = l->next) - { - MetaOutput *output = l->data; - MetaCrtc *assigned_crtc; - - assigned_crtc = meta_output_get_assigned_crtc (output); - if (assigned_crtc == crtc) - { - MetaKmsConnector *kms_connector = - meta_output_kms_get_kms_connector (META_OUTPUT_KMS (output)); - - connectors = g_list_prepend (connectors, kms_connector); - } - } - - return connectors; -} - -void -meta_crtc_kms_maybe_set_gamma (MetaCrtcKms *crtc_kms, - MetaKmsDevice *kms_device) -{ - MetaGpu *gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms)); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerNative *monitor_manager_native = - META_MONITOR_MANAGER_NATIVE (monitor_manager); - MetaKms *kms = meta_kms_device_get_kms (kms_device); - MetaKmsUpdate *kms_update; - MetaKmsCrtcGamma *gamma; - - if (crtc_kms->is_gamma_valid) - return; - - gamma = meta_monitor_manager_native_get_cached_crtc_gamma (monitor_manager_native, - crtc_kms); - if (!gamma) - return; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_kms_update_set_crtc_gamma (kms_update, - meta_crtc_kms_get_kms_crtc (crtc_kms), - gamma->size, - gamma->red, - gamma->green, - gamma->blue); - - crtc_kms->is_gamma_valid = TRUE; -} - -void -meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms, - MetaKmsUpdate *kms_update) -{ - MetaCrtc *crtc = META_CRTC (crtc_kms); - MetaGpu *gpu = meta_crtc_get_gpu (crtc); - GList *connectors; - MetaKmsMode *kms_mode; - - connectors = generate_crtc_connector_list (gpu, crtc); - - if (connectors) - { - const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc); - MetaCrtcModeKms *crtc_mode_kms = META_CRTC_MODE_KMS (crtc_config->mode); - - kms_mode = meta_crtc_mode_kms_get_kms_mode (crtc_mode_kms); - - meta_topic (META_DEBUG_KMS, - "Setting CRTC (%" G_GUINT64_FORMAT ") mode to %s", - meta_crtc_get_id (crtc), meta_kms_mode_get_name (kms_mode)); - } - else - { - kms_mode = NULL; - - meta_topic (META_DEBUG_KMS, - "Unsetting CRTC (%" G_GUINT64_FORMAT ") mode", - meta_crtc_get_id (crtc)); - } - - meta_kms_update_mode_set (kms_update, - meta_crtc_kms_get_kms_crtc (crtc_kms), - g_steal_pointer (&connectors), - kms_mode); -} - -MetaKmsCrtc * -meta_crtc_kms_get_kms_crtc (MetaCrtcKms *crtc_kms) -{ - return crtc_kms->kms_crtc; -} - -/** - * meta_crtc_kms_get_modifiers: - * @crtc_kms: a #MetaCrtc object that has to be a #MetaCrtcKms - * @format: a DRM pixel format - * - * Returns a pointer to a #GArray containing all the supported - * modifiers for the given DRM pixel format on the CRTC's primary - * plane. The array element type is uint64_t. - * - * The caller must not modify or destroy the array or its contents. - * - * Returns NULL if the modifiers are not known or the format is not - * supported. - */ -GArray * -meta_crtc_kms_get_modifiers (MetaCrtcKms *crtc_kms, - uint32_t format) -{ - return meta_kms_plane_get_modifiers_for_format (crtc_kms->primary_plane, - format); -} - -/** - * meta_crtc_kms_copy_drm_format_list: - * @crtc_kms: a #MetaCrtc object that has to be a #MetaCrtcKms - * - * Returns a new #GArray that the caller must destroy. The array - * contains all the DRM pixel formats the CRTC supports on - * its primary plane. The array element type is uint32_t. - */ -GArray * -meta_crtc_kms_copy_drm_format_list (MetaCrtcKms *crtc_kms) -{ - return meta_kms_plane_copy_drm_format_list (crtc_kms->primary_plane); -} - -/** - * meta_crtc_kms_supports_format: - * @crtc_kms: a #MetaCrtcKms - * @drm_format: a DRM pixel format - * - * Returns true if the CRTC supports the format on its primary plane. - */ -gboolean -meta_crtc_kms_supports_format (MetaCrtcKms *crtc_kms, - uint32_t drm_format) -{ - return meta_kms_plane_is_format_supported (crtc_kms->primary_plane, - drm_format); -} - -void -meta_crtc_kms_invalidate_gamma (MetaCrtcKms *crtc_kms) -{ - crtc_kms->is_gamma_valid = FALSE; -} - -MetaCrtcKms * -meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc) -{ - return g_object_get_qdata (G_OBJECT (kms_crtc), kms_crtc_crtc_kms_quark); -} - -MetaCrtcKms * -meta_crtc_kms_new (MetaGpuKms *gpu_kms, - MetaKmsCrtc *kms_crtc) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - MetaKmsDevice *kms_device; - MetaCrtcKms *crtc_kms; - MetaKmsPlane *primary_plane; - - kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - primary_plane = meta_kms_device_get_primary_plane_for (kms_device, - kms_crtc); - crtc_kms = g_object_new (META_TYPE_CRTC_KMS, - "id", (uint64_t) meta_kms_crtc_get_id (kms_crtc), - "gpu", gpu, - NULL); - - crtc_kms->kms_crtc = kms_crtc; - crtc_kms->primary_plane = primary_plane; - - if (!kms_crtc_crtc_kms_quark) - { - kms_crtc_crtc_kms_quark = - g_quark_from_static_string ("meta-kms-crtc-crtc-kms-quark"); - } - - g_object_set_qdata (G_OBJECT (kms_crtc), kms_crtc_crtc_kms_quark, crtc_kms); - - return crtc_kms; -} - -static void -meta_crtc_kms_dispose (GObject *object) -{ - MetaCrtcKms *crtc_kms = META_CRTC_KMS (object); - - g_clear_pointer (&crtc_kms->cursor_renderer_private, - crtc_kms->cursor_renderer_private_destroy_notify); - - G_OBJECT_CLASS (meta_crtc_kms_parent_class)->dispose (object); -} - -static void -meta_crtc_kms_init (MetaCrtcKms *crtc_kms) -{ -} - -static void -meta_crtc_kms_class_init (MetaCrtcKmsClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaCrtcNativeClass *crtc_native_class = META_CRTC_NATIVE_CLASS (klass); - - object_class->dispose = meta_crtc_kms_dispose; - - crtc_native_class->is_transform_handled = meta_crtc_kms_is_transform_handled; -} diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h deleted file mode 100644 index f8d241bbb..000000000 --- a/src/backends/native/meta-crtc-kms.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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. - */ - -#ifndef META_CRTC_KMS_H -#define META_CRTC_KMS_H - -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "backends/meta-backend-types.h" -#include "backends/meta-crtc.h" -#include "backends/native/meta-crtc-native.h" -#include "backends/native/meta-drm-buffer.h" -#include "backends/native/meta-gpu-kms.h" -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-update.h" - -#define META_TYPE_CRTC_KMS (meta_crtc_kms_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCrtcKms, meta_crtc_kms, - META, CRTC_KMS, - MetaCrtcNative) - -gpointer meta_crtc_kms_get_cursor_renderer_private (MetaCrtcKms *crtc_kms); - -void meta_crtc_kms_set_cursor_renderer_private (MetaCrtcKms *crtc_kms, - gpointer cursor_renderer_private, - GDestroyNotify destroy_notify); - -void meta_crtc_kms_apply_transform (MetaCrtcKms *crtc_kms, - MetaKmsPlaneAssignment *kms_plane_assignment); - -void meta_crtc_kms_assign_primary_plane (MetaCrtcKms *crtc_kms, - MetaDrmBuffer *buffer, - MetaKmsUpdate *kms_update); - -void meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms, - MetaKmsUpdate *kms_update); - -void meta_crtc_kms_set_is_underscanning (MetaCrtcKms *crtc_kms, - gboolean is_underscanning); - -MetaKmsCrtc * meta_crtc_kms_get_kms_crtc (MetaCrtcKms *crtc_kms); - -GArray * meta_crtc_kms_get_modifiers (MetaCrtcKms *crtc_kms, - uint32_t format); - -GArray * -meta_crtc_kms_copy_drm_format_list (MetaCrtcKms *crtc_kms); - -gboolean -meta_crtc_kms_supports_format (MetaCrtcKms *crtc_kms, - uint32_t drm_format); - -void meta_crtc_kms_invalidate_gamma (MetaCrtcKms *crtc_kms); - -void meta_crtc_kms_maybe_set_gamma (MetaCrtcKms *crtc_kms, - MetaKmsDevice *kms_device); - -MetaCrtcKms * meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc); - -MetaCrtcKms * meta_crtc_kms_new (MetaGpuKms *gpu_kms, - MetaKmsCrtc *kms_crtc); - -#endif /* META_CRTC_KMS_H */ diff --git a/src/backends/native/meta-crtc-mode-kms.c b/src/backends/native/meta-crtc-mode-kms.c deleted file mode 100644 index 053367cfd..000000000 --- a/src/backends/native/meta-crtc-mode-kms.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2017-2020 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. - */ - -#include "config.h" - -#include "backends/native/meta-crtc-mode-kms.h" - -#include "backends/native/meta-kms-mode.h" -#include "backends/native/meta-kms-utils.h" - -struct _MetaCrtcModeKms -{ - MetaCrtcMode parent; - - MetaKmsMode *kms_mode; -}; - -G_DEFINE_TYPE (MetaCrtcModeKms, meta_crtc_mode_kms, - META_TYPE_CRTC_MODE) - -MetaKmsMode * -meta_crtc_mode_kms_get_kms_mode (MetaCrtcModeKms *mode_kms) -{ - return mode_kms->kms_mode; -} - -MetaCrtcModeKms * -meta_crtc_mode_kms_new (MetaKmsMode *kms_mode, - uint64_t id) -{ - const drmModeModeInfo *drm_mode = meta_kms_mode_get_drm_mode (kms_mode); - g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL; - g_autofree char *crtc_mode_name = NULL; - MetaCrtcModeKms *mode_kms; - - crtc_mode_info = meta_crtc_mode_info_new (); - crtc_mode_info->width = drm_mode->hdisplay; - crtc_mode_info->height = drm_mode->vdisplay; - crtc_mode_info->flags = drm_mode->flags; - crtc_mode_info->refresh_rate = - meta_calculate_drm_mode_refresh_rate (drm_mode); - crtc_mode_info->vblank_duration_us = - meta_calculate_drm_mode_vblank_duration_us (drm_mode); - - crtc_mode_name = g_strndup (drm_mode->name, DRM_DISPLAY_MODE_LEN); - mode_kms = g_object_new (META_TYPE_CRTC_MODE_KMS, - "id", id, - "name", crtc_mode_name, - "info", crtc_mode_info, - NULL); - - mode_kms->kms_mode = kms_mode; - - return mode_kms; -} - -static void -meta_crtc_mode_kms_init (MetaCrtcModeKms *mode_kms) -{ -} - -static void -meta_crtc_mode_kms_class_init (MetaCrtcModeKmsClass *klass) -{ -} diff --git a/src/backends/native/meta-crtc-mode-kms.h b/src/backends/native/meta-crtc-mode-kms.h deleted file mode 100644 index f39268612..000000000 --- a/src/backends/native/meta-crtc-mode-kms.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2017-2020 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. - */ - -#ifndef META_CRTC_MODE_KMS_H -#define META_CRTC_MODE_KMS_H - -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "backends/meta-crtc-mode.h" -#include "backends/native/meta-kms-types.h" - -#define META_TYPE_CRTC_MODE_KMS (meta_crtc_mode_kms_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCrtcModeKms, meta_crtc_mode_kms, - META, CRTC_MODE_KMS, - MetaCrtcMode) - -MetaKmsMode * meta_crtc_mode_kms_get_kms_mode (MetaCrtcModeKms *mode_kms); - -MetaCrtcModeKms * meta_crtc_mode_kms_new (MetaKmsMode *kms_mode, - uint64_t id); - -#endif /* META_CRTC_MODE_KMS_H */ diff --git a/src/backends/native/meta-crtc-mode-virtual.c b/src/backends/native/meta-crtc-mode-virtual.c deleted file mode 100644 index 3bb883049..000000000 --- a/src/backends/native/meta-crtc-mode-virtual.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#include "config.h" - -#include "backends/native/meta-crtc-mode-virtual.h" - -#include "backends/meta-virtual-monitor.h" - -struct _MetaCrtcModeVirtual -{ - MetaCrtcMode parent; -}; - -#define META_CRTC_MODE_VIRTUAL_ID_BIT (((uint64_t) 1) << 63) - -G_DEFINE_TYPE (MetaCrtcModeVirtual, meta_crtc_mode_virtual, - META_TYPE_CRTC_MODE) - -MetaCrtcModeVirtual * -meta_crtc_mode_virtual_new (uint64_t id, - const MetaVirtualMonitorInfo *info) -{ - g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL; - g_autofree char *crtc_mode_name = NULL; - MetaCrtcModeVirtual *mode_virtual; - - crtc_mode_info = meta_crtc_mode_info_new (); - crtc_mode_info->width = info->width; - crtc_mode_info->height = info->height; - crtc_mode_info->refresh_rate = info->refresh_rate; - - crtc_mode_name = g_strdup_printf ("%dx%d@%f", - info->width, - info->height, - info->refresh_rate); - mode_virtual = g_object_new (META_TYPE_CRTC_MODE_VIRTUAL, - "id", META_CRTC_MODE_VIRTUAL_ID_BIT | id, - "name", crtc_mode_name, - "info", crtc_mode_info, - NULL); - - return mode_virtual; -} - -static void -meta_crtc_mode_virtual_init (MetaCrtcModeVirtual *mode_virtual) -{ -} - -static void -meta_crtc_mode_virtual_class_init (MetaCrtcModeVirtualClass *klass) -{ -} diff --git a/src/backends/native/meta-crtc-mode-virtual.h b/src/backends/native/meta-crtc-mode-virtual.h deleted file mode 100644 index e3ddb289c..000000000 --- a/src/backends/native/meta-crtc-mode-virtual.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#ifndef META_CRTC_MODE_VIRTUAL_H -#define META_CRTC_MODE_VIRTUAL_H - -#include "backends/meta-backend-types.h" -#include "backends/meta-crtc-mode.h" - -#define META_TYPE_CRTC_MODE_VIRTUAL (meta_crtc_mode_virtual_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCrtcModeVirtual, meta_crtc_mode_virtual, - META, CRTC_MODE_VIRTUAL, - MetaCrtcMode) - -MetaCrtcModeVirtual * meta_crtc_mode_virtual_new (uint64_t id, - const MetaVirtualMonitorInfo *info); - -#endif /* META_CRTC_MODE_VIRTUAL_H */ diff --git a/src/backends/native/meta-crtc-native.c b/src/backends/native/meta-crtc-native.c deleted file mode 100644 index 5e5751780..000000000 --- a/src/backends/native/meta-crtc-native.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#include "config.h" - -#include "backends/native/meta-crtc-native.h" - -G_DEFINE_ABSTRACT_TYPE (MetaCrtcNative, meta_crtc_native, - META_TYPE_CRTC) - -gboolean -meta_crtc_native_is_transform_handled (MetaCrtcNative *crtc_native, - MetaMonitorTransform transform) -{ - MetaCrtcNativeClass *klass = META_CRTC_NATIVE_GET_CLASS (crtc_native); - - return klass->is_transform_handled (crtc_native, transform); -} - -static void -meta_crtc_native_init (MetaCrtcNative *crtc_native) -{ -} - -static void -meta_crtc_native_class_init (MetaCrtcNativeClass *klass) -{ -} diff --git a/src/backends/native/meta-crtc-native.h b/src/backends/native/meta-crtc-native.h deleted file mode 100644 index 0c16e5895..000000000 --- a/src/backends/native/meta-crtc-native.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#ifndef META_CRTC_NATIVE_H -#define META_CRTC_NATIVE_H - -#include "backends/meta-crtc.h" - -#define META_TYPE_CRTC_NATIVE (meta_crtc_native_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaCrtcNative, meta_crtc_native, - META, CRTC_NATIVE, - MetaCrtc) - -struct _MetaCrtcNativeClass -{ - MetaCrtcClass parent_class; - - gboolean (* is_transform_handled) (MetaCrtcNative *crtc_native, - MetaMonitorTransform monitor_transform); -}; - -gboolean meta_crtc_native_is_transform_handled (MetaCrtcNative *crtc_native, - MetaMonitorTransform transform); - -#endif /* META_CRTC_NATIVE_H */ diff --git a/src/backends/native/meta-crtc-virtual.c b/src/backends/native/meta-crtc-virtual.c deleted file mode 100644 index eee346a23..000000000 --- a/src/backends/native/meta-crtc-virtual.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#include "config.h" - -#include "backends/native/meta-crtc-virtual.h" - -struct _MetaCrtcVirtual -{ - MetaCrtcNative parent; -}; - -#define META_CRTC_VIRTUAL_ID_BIT (((uint64_t) 1) << 63) - -G_DEFINE_TYPE (MetaCrtcVirtual, meta_crtc_virtual, META_TYPE_CRTC_NATIVE) - -MetaCrtcVirtual * -meta_crtc_virtual_new (uint64_t id) -{ - return g_object_new (META_TYPE_CRTC_VIRTUAL, - "id", META_CRTC_VIRTUAL_ID_BIT | id, - NULL); -} - -static gboolean -meta_crtc_virtual_is_transform_handled (MetaCrtcNative *crtc_native, - MetaMonitorTransform transform) -{ - return transform == META_MONITOR_TRANSFORM_NORMAL; -} - -static void -meta_crtc_virtual_init (MetaCrtcVirtual *crtc_virtual) -{ -} - -static void -meta_crtc_virtual_class_init (MetaCrtcVirtualClass *klass) -{ - MetaCrtcNativeClass *crtc_native_class = META_CRTC_NATIVE_CLASS (klass); - - crtc_native_class->is_transform_handled = - meta_crtc_virtual_is_transform_handled; -} diff --git a/src/backends/native/meta-crtc-virtual.h b/src/backends/native/meta-crtc-virtual.h deleted file mode 100644 index 89b1bcc7a..000000000 --- a/src/backends/native/meta-crtc-virtual.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#ifndef META_CRTC_VIRTUAL_H -#define META_CRTC_VIRTUAL_H - -#include "backends/native/meta-crtc-native.h" - -#define META_TYPE_CRTC_VIRTUAL (meta_crtc_virtual_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCrtcVirtual, meta_crtc_virtual, - META, CRTC_VIRTUAL, - MetaCrtcNative) - -MetaCrtcVirtual * meta_crtc_virtual_new (uint64_t id); - -#endif /* META_CRTC_VIRTUAL_H */ diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c deleted file mode 100644 index effa0851d..000000000 --- a/src/backends/native/meta-cursor-renderer-native.c +++ /dev/null @@ -1,1878 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * Copyright 2020 DisplayLink (UK) Ltd. - * - * 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 <jstpierre@mecheye.net> - */ - -#include "config.h" - -#include "backends/native/meta-cursor-renderer-native.h" - -#include <string.h> -#include <gbm.h> -#include <xf86drm.h> -#include <errno.h> - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-sprite-xcursor.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-output.h" -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-plane.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-renderer-native.h" -#include "core/boxes-private.h" -#include "meta/boxes.h" -#include "meta/meta-backend.h" -#include "meta/util.h" - -#ifdef HAVE_WAYLAND -#include "wayland/meta-cursor-sprite-wayland.h" -#include "wayland/meta-wayland-buffer.h" -#endif - -#ifndef DRM_CAP_CURSOR_WIDTH -#define DRM_CAP_CURSOR_WIDTH 0x8 -#endif -#ifndef DRM_CAP_CURSOR_HEIGHT -#define DRM_CAP_CURSOR_HEIGHT 0x9 -#endif - -/* When animating a cursor, we usually call drmModeSetCursor2 once per frame. - * Though, testing shows that we need to triple buffer the cursor buffer in - * order to avoid glitches when animating the cursor, at least when running on - * Intel. The reason for this might be (but is not confirmed to be) due to - * the user space gbm_bo cache, making us reuse and overwrite the kernel side - * buffer content before it was scanned out. To avoid this, we keep a user space - * reference to each buffer we set until at least one frame after it was drawn. - * In effect, this means we three active cursor gbm_bo's: one that that just has - * been set, one that was previously set and may or may not have been scanned - * out, and one pending that will be replaced if the cursor sprite changes. - */ -#define HW_CURSOR_BUFFER_COUNT 3 - -static GQuark quark_cursor_sprite = 0; - -typedef struct _CrtcCursorData -{ - MetaDrmBuffer *buffer; - gboolean needs_sync_position; - gboolean hw_state_invalidated; -} CrtcCursorData; - -struct _MetaCursorRendererNative -{ - MetaCursorRenderer parent; -}; - -struct _MetaCursorRendererNativePrivate -{ - MetaBackend *backend; - - gboolean has_hw_cursor; - - MetaCursorSprite *last_cursor; - guint animation_timeout_id; -}; -typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate; - -typedef struct _MetaCursorRendererNativeGpuData -{ - gboolean hw_cursor_broken; - - uint64_t cursor_width; - uint64_t cursor_height; -} MetaCursorRendererNativeGpuData; - -typedef enum _MetaCursorBufferState -{ - META_CURSOR_BUFFER_STATE_NONE, - META_CURSOR_BUFFER_STATE_SET, - META_CURSOR_BUFFER_STATE_INVALIDATED, -} MetaCursorBufferState; - -typedef struct _MetaCursorNativeGpuState -{ - MetaGpu *gpu; - unsigned int active_buffer_idx; - MetaCursorBufferState pending_buffer_state; - MetaDrmBuffer *buffers[HW_CURSOR_BUFFER_COUNT]; -} MetaCursorNativeGpuState; - -typedef struct _MetaCursorNativePrivate -{ - GHashTable *gpu_states; - - struct { - gboolean can_preprocess; - float current_relative_scale; - MetaMonitorTransform current_relative_transform; - } preprocess_state; -} MetaCursorNativePrivate; - -static GQuark quark_cursor_renderer_native_gpu_data = 0; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER); - -static void -on_kms_update_result (const MetaKmsFeedback *kms_feedback, - gpointer user_data); - -static void -realize_cursor_sprite (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - GList *gpus); - -static MetaCursorNativeGpuState * -get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms); - -static MetaCursorNativeGpuState * -ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms); - -static void -invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite); - -static MetaCursorNativePrivate * -ensure_cursor_priv (MetaCursorSprite *cursor_sprite); - -static MetaCursorNativePrivate * -get_cursor_priv (MetaCursorSprite *cursor_sprite); - -static MetaCursorRendererNativeGpuData * -meta_cursor_renderer_native_gpu_data_from_gpu (MetaGpuKms *gpu_kms) -{ - return g_object_get_qdata (G_OBJECT (gpu_kms), - quark_cursor_renderer_native_gpu_data); -} - -static MetaCursorRendererNativeGpuData * -meta_create_cursor_renderer_native_gpu_data (MetaGpuKms *gpu_kms) -{ - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - - cursor_renderer_gpu_data = g_new0 (MetaCursorRendererNativeGpuData, 1); - g_object_set_qdata_full (G_OBJECT (gpu_kms), - quark_cursor_renderer_native_gpu_data, - cursor_renderer_gpu_data, - g_free); - - return cursor_renderer_gpu_data; -} - -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); - - g_clear_handle_id (&priv->animation_timeout_id, g_source_remove); - - G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object); -} - -static unsigned int -get_pending_cursor_sprite_buffer_index (MetaCursorNativeGpuState *cursor_gpu_state) -{ - return (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT; -} - -static MetaDrmBuffer * -get_pending_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state) -{ - unsigned int pending_buffer_idx; - - pending_buffer_idx = - get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - return cursor_gpu_state->buffers[pending_buffer_idx]; -} - -static MetaDrmBuffer * -get_active_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state) -{ - return cursor_gpu_state->buffers[cursor_gpu_state->active_buffer_idx]; -} - -static void -set_pending_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms, - MetaDrmBuffer *buffer) -{ - MetaCursorNativePrivate *cursor_priv; - MetaCursorNativeGpuState *cursor_gpu_state; - unsigned int pending_buffer_idx; - - cursor_priv = ensure_cursor_priv (cursor_sprite); - cursor_gpu_state = ensure_cursor_gpu_state (cursor_priv, gpu_kms); - - pending_buffer_idx = - get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - cursor_gpu_state->buffers[pending_buffer_idx] = buffer; - cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_SET; -} - -static void -calculate_crtc_cursor_hotspot (MetaCursorSprite *cursor_sprite, - int *cursor_hotspot_x, - int *cursor_hotspot_y) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - int hot_x, hot_y; - int width, height; - float scale; - MetaMonitorTransform transform; - - scale = cursor_priv->preprocess_state.current_relative_scale; - transform = cursor_priv->preprocess_state.current_relative_transform; - - meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y); - width = meta_cursor_sprite_get_width (cursor_sprite); - height = meta_cursor_sprite_get_height (cursor_sprite); - meta_monitor_transform_transform_point (transform, - width, height, - hot_x, hot_y, - &hot_x, &hot_y); - *cursor_hotspot_x = (int) roundf (hot_x * scale); - *cursor_hotspot_y = (int) roundf (hot_y * scale); -} - -static CrtcCursorData * -ensure_crtc_cursor_data (MetaCrtcKms *crtc_kms) -{ - CrtcCursorData *crtc_cursor_data; - - crtc_cursor_data = meta_crtc_kms_get_cursor_renderer_private (crtc_kms); - if (!crtc_cursor_data) - { - crtc_cursor_data = g_new0 (CrtcCursorData, 1); - crtc_cursor_data->hw_state_invalidated = TRUE; - meta_crtc_kms_set_cursor_renderer_private (crtc_kms, - crtc_cursor_data, - g_free); - } - - return crtc_cursor_data; -} - -static void -assign_cursor_plane (MetaCursorRendererNative *native, - MetaCrtcKms *crtc_kms, - int x, - int y, - MetaCursorSprite *cursor_sprite) -{ - MetaCrtc *crtc = META_CRTC (crtc_kms); - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - MetaCursorNativeGpuState *cursor_gpu_state = - get_cursor_gpu_state (cursor_priv, gpu_kms); - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsPlane *cursor_plane; - MetaDrmBuffer *buffer; - int cursor_width, cursor_height; - MetaFixed16Rectangle src_rect; - MetaRectangle dst_rect; - MetaDrmBuffer *crtc_buffer; - MetaKmsAssignPlaneFlag flags; - CrtcCursorData *crtc_cursor_data; - int cursor_hotspot_x; - int cursor_hotspot_y; - MetaKmsUpdate *kms_update; - MetaKmsPlaneAssignment *plane_assignment; - - if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) - buffer = get_pending_cursor_sprite_buffer (cursor_gpu_state); - else - buffer = get_active_cursor_sprite_buffer (cursor_gpu_state); - - kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - kms_device = meta_kms_crtc_get_device (kms_crtc); - cursor_plane = meta_kms_device_get_cursor_plane_for (kms_device, kms_crtc); - g_return_if_fail (cursor_plane); - - cursor_width = cursor_renderer_gpu_data->cursor_width; - cursor_height = cursor_renderer_gpu_data->cursor_height; - src_rect = (MetaFixed16Rectangle) { - .x = meta_fixed_16_from_int (0), - .y = meta_fixed_16_from_int (0), - .width = meta_fixed_16_from_int (cursor_width), - .height = meta_fixed_16_from_int (cursor_height), - }; - dst_rect = (MetaRectangle) { - .x = x, - .y = y, - .width = cursor_width, - .height = cursor_height, - }; - - flags = META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL; - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_buffer = crtc_cursor_data->buffer; - if (!crtc_cursor_data->hw_state_invalidated && buffer == crtc_buffer) - flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED; - - kms_update = - meta_kms_ensure_pending_update (meta_kms_device_get_kms (kms_device), - meta_kms_crtc_get_device (kms_crtc)); - plane_assignment = meta_kms_update_assign_plane (kms_update, - kms_crtc, - cursor_plane, - buffer, - src_rect, - dst_rect, - flags); - - calculate_crtc_cursor_hotspot (cursor_sprite, - &cursor_hotspot_x, - &cursor_hotspot_y); - meta_kms_plane_assignment_set_cursor_hotspot (plane_assignment, - cursor_hotspot_x, - cursor_hotspot_y); - - meta_kms_update_add_result_listener (kms_update, - on_kms_update_result, - native); - - crtc_cursor_data->buffer = buffer; - - if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) - { - cursor_gpu_state->active_buffer_idx = - (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT; - cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_NONE; - } -} - -static float -calculate_cursor_crtc_sprite_scale (MetaCursorSprite *cursor_sprite, - MetaLogicalMonitor *logical_monitor) -{ - if (meta_is_stage_views_scaled ()) - { - return (meta_logical_monitor_get_scale (logical_monitor) * - meta_cursor_sprite_get_texture_scale (cursor_sprite)); - } - else - { - return 1.0; - } -} - -static void -set_crtc_cursor (MetaCursorRendererNative *cursor_renderer_native, - MetaRendererView *view, - MetaCrtc *crtc, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRenderer *cursor_renderer = - META_CURSOR_RENDERER (cursor_renderer_native); - MetaOutput *output = meta_crtc_get_outputs (crtc)->data; - MetaMonitor *monitor = meta_output_get_monitor (output); - MetaLogicalMonitor *logical_monitor = - meta_monitor_get_logical_monitor (monitor); - const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc); - graphene_rect_t rect; - graphene_rect_t local_crtc_rect; - graphene_rect_t local_cursor_rect; - float view_scale; - float crtc_cursor_x, crtc_cursor_y; - CoglTexture *texture; - int tex_width, tex_height; - float cursor_crtc_scale; - MetaRectangle cursor_rect; - MetaMonitorTransform transform; - MetaMonitorTransform inverted_transform; - MetaMonitorMode *monitor_mode; - MetaMonitorCrtcMode *monitor_crtc_mode; - const MetaCrtcModeInfo *crtc_mode_info; - - view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view)); - - rect = meta_cursor_renderer_calculate_rect (cursor_renderer, cursor_sprite); - local_cursor_rect = - GRAPHENE_RECT_INIT (rect.origin.x - logical_monitor->rect.x, - rect.origin.y - logical_monitor->rect.y, - rect.size.width, - rect.size.height); - - local_crtc_rect = crtc_config->layout; - graphene_rect_offset (&local_crtc_rect, - -logical_monitor->rect.x, - -logical_monitor->rect.y); - - crtc_cursor_x = (local_cursor_rect.origin.x - - local_crtc_rect.origin.x) * view_scale; - crtc_cursor_y = (local_cursor_rect.origin.y - - local_crtc_rect.origin.y) * view_scale; - - texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - tex_width = cogl_texture_get_width (texture); - tex_height = cogl_texture_get_height (texture); - - cursor_crtc_scale = - calculate_cursor_crtc_sprite_scale (cursor_sprite, - logical_monitor); - - cursor_rect = (MetaRectangle) { - .x = floorf (crtc_cursor_x), - .y = floorf (crtc_cursor_y), - .width = roundf (tex_width * cursor_crtc_scale), - .height = roundf (tex_height * cursor_crtc_scale) - }; - - transform = meta_logical_monitor_get_transform (logical_monitor); - transform = meta_monitor_logical_to_crtc_transform (monitor, transform); - - inverted_transform = meta_monitor_transform_invert (transform); - - monitor_mode = meta_monitor_get_current_mode (monitor); - monitor_crtc_mode = meta_monitor_get_crtc_mode_for_output (monitor, - monitor_mode, - output); - crtc_mode_info = meta_crtc_mode_get_info (monitor_crtc_mode->crtc_mode); - meta_rectangle_transform (&cursor_rect, - inverted_transform, - crtc_mode_info->width, - crtc_mode_info->height, - &cursor_rect); - - assign_cursor_plane (cursor_renderer_native, - META_CRTC_KMS (crtc), - cursor_rect.x, - cursor_rect.y, - cursor_sprite); -} - -static void -unset_crtc_cursor (MetaCursorRendererNative *native, - MetaCrtc *crtc) -{ - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); - CrtcCursorData *crtc_cursor_data; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsPlane *cursor_plane; - MetaDrmBuffer *crtc_buffer; - - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_buffer = crtc_cursor_data->buffer; - if (!crtc_cursor_data->hw_state_invalidated && !crtc_buffer) - return; - - kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - kms_device = meta_kms_crtc_get_device (kms_crtc); - cursor_plane = meta_kms_device_get_cursor_plane_for (kms_device, kms_crtc); - - if (cursor_plane) - { - MetaKms *kms = meta_kms_device_get_kms (kms_device); - MetaKmsUpdate *kms_update; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane); - } - - crtc_cursor_data->buffer = NULL; -} - -static void -disable_hw_cursor_for_crtc (MetaKmsCrtc *kms_crtc, - const GError *error) -{ - MetaCrtcKms *crtc_kms = meta_crtc_kms_from_kms_crtc (kms_crtc); - MetaCrtc *crtc = META_CRTC (crtc_kms); - MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - - g_warning ("Failed to set hardware cursor (%s), " - "using OpenGL from now on", - error->message); - cursor_renderer_gpu_data->hw_cursor_broken = TRUE; -} - -void -meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native, - MetaRendererView *view) -{ - MetaCursorRenderer *cursor_renderer = - META_CURSOR_RENDERER (cursor_renderer_native); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); - MetaCursorSprite *cursor_sprite; - graphene_rect_t cursor_rect; - cairo_rectangle_int_t view_layout; - graphene_rect_t view_rect; - CrtcCursorData *crtc_cursor_data; - - if (meta_monitor_manager_get_power_save_mode (monitor_manager) != - META_POWER_SAVE_ON) - return; - - if (!meta_crtc_get_gpu (crtc)) - return; - - crtc_cursor_data = ensure_crtc_cursor_data (META_CRTC_KMS (crtc)); - if (!crtc_cursor_data->hw_state_invalidated && - !crtc_cursor_data->needs_sync_position) - return; - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - if (!cursor_sprite) - goto unset_cursor; - - if (!priv->has_hw_cursor) - goto unset_cursor; - - cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer, - cursor_sprite); - clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout); - view_rect = GRAPHENE_RECT_INIT (view_layout.x, view_layout.y, - view_layout.width, view_layout.height); - if (!graphene_rect_intersection (&cursor_rect, &view_rect, NULL)) - goto unset_cursor; - - set_crtc_cursor (cursor_renderer_native, view, crtc, cursor_sprite); - - meta_cursor_renderer_emit_painted (cursor_renderer, - cursor_sprite, - CLUTTER_STAGE_VIEW (view)); - - crtc_cursor_data->needs_sync_position = FALSE; - crtc_cursor_data->hw_state_invalidated = FALSE; - return; - -unset_cursor: - unset_crtc_cursor (cursor_renderer_native, crtc); - - crtc_cursor_data = ensure_crtc_cursor_data (META_CRTC_KMS (crtc)); - crtc_cursor_data->hw_state_invalidated = FALSE; -} - -static gboolean -has_valid_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativePrivate *cursor_priv; - MetaCursorNativeGpuState *cursor_gpu_state; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (!cursor_priv) - return FALSE; - - cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); - if (!cursor_gpu_state) - return FALSE; - - switch (cursor_gpu_state->pending_buffer_state) - { - case META_CURSOR_BUFFER_STATE_NONE: - return get_active_cursor_sprite_buffer (cursor_gpu_state) != NULL; - case META_CURSOR_BUFFER_STATE_SET: - return TRUE; - case META_CURSOR_BUFFER_STATE_INVALIDATED: - return FALSE; - } - - g_assert_not_reached (); - - return FALSE; -} - -static void -set_can_preprocess (MetaCursorSprite *cursor_sprite, - float scale, - MetaMonitorTransform transform) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - cursor_priv->preprocess_state.current_relative_scale = scale; - cursor_priv->preprocess_state.current_relative_transform = transform; - cursor_priv->preprocess_state.can_preprocess = TRUE; - - invalidate_cursor_gpu_state (cursor_sprite); -} - -static void -unset_can_preprocess (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - memset (&cursor_priv->preprocess_state, - 0, - sizeof (cursor_priv->preprocess_state)); - cursor_priv->preprocess_state.can_preprocess = FALSE; - - invalidate_cursor_gpu_state (cursor_sprite); -} - -static gboolean -get_can_preprocess (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - return cursor_priv->preprocess_state.can_preprocess; -} - -static float -get_current_relative_scale (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - return cursor_priv->preprocess_state.current_relative_scale; -} - -static MetaMonitorTransform -get_current_relative_transform (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - return cursor_priv->preprocess_state.current_relative_transform; -} - -static void -has_cursor_plane (MetaLogicalMonitor *logical_monitor, - MetaMonitor *monitor, - MetaOutput *output, - MetaCrtc *crtc, - gpointer user_data) -{ - gboolean *has_cursor_planes = user_data; - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); - - *has_cursor_planes &= !!meta_kms_device_get_cursor_plane_for (kms_device, - kms_crtc); -} - -static gboolean -crtcs_has_cursor_planes (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *logical_monitors; - GList *l; - graphene_rect_t cursor_rect; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaRectangle logical_monitor_layout; - graphene_rect_t logical_monitor_rect; - gboolean has_cursor_planes; - - logical_monitor_layout = - meta_logical_monitor_get_layout (logical_monitor); - logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor_layout); - - if (!graphene_rect_intersection (&cursor_rect, &logical_monitor_rect, - NULL)) - continue; - - has_cursor_planes = TRUE; - meta_logical_monitor_foreach_crtc (logical_monitor, - has_cursor_plane, - &has_cursor_planes); - if (!has_cursor_planes) - return FALSE; - } - - return TRUE; -} - -static gboolean -get_common_crtc_sprite_scale_for_logical_monitors (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - float *out_scale) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - graphene_rect_t cursor_rect; - float scale = 1.0; - gboolean has_visible_crtc_sprite = FALSE; - GList *logical_monitors; - GList *l; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - graphene_rect_t logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor->rect); - float tmp_scale; - - if (!graphene_rect_intersection (&cursor_rect, - &logical_monitor_rect, - NULL)) - continue; - - tmp_scale = - calculate_cursor_crtc_sprite_scale (cursor_sprite, logical_monitor); - - if (has_visible_crtc_sprite && scale != tmp_scale) - return FALSE; - - has_visible_crtc_sprite = TRUE; - scale = tmp_scale; - } - - if (!has_visible_crtc_sprite) - return FALSE; - - *out_scale = scale; - return TRUE; -} - -static gboolean -get_common_crtc_sprite_transform_for_logical_monitors (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - MetaMonitorTransform *out_transform) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - graphene_rect_t cursor_rect; - MetaMonitorTransform transform = META_MONITOR_TRANSFORM_NORMAL; - gboolean has_visible_crtc_sprite = FALSE; - GList *logical_monitors; - GList *l; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - graphene_rect_t logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor->rect); - MetaMonitorTransform logical_transform, tmp_transform; - GList *monitors, *l_mon; - - if (!graphene_rect_intersection (&cursor_rect, - &logical_monitor_rect, - NULL)) - continue; - - logical_transform = meta_logical_monitor_get_transform (logical_monitor); - monitors = meta_logical_monitor_get_monitors (logical_monitor); - for (l_mon = monitors; l_mon; l_mon = l_mon->next) - { - MetaMonitor *monitor = l_mon->data; - - tmp_transform = meta_monitor_transform_relative_transform ( - meta_cursor_sprite_get_texture_transform (cursor_sprite), - meta_monitor_logical_to_crtc_transform (monitor, logical_transform)); - - if (has_visible_crtc_sprite && transform != tmp_transform) - return FALSE; - - has_visible_crtc_sprite = TRUE; - transform = tmp_transform; - } - } - - if (!has_visible_crtc_sprite) - return FALSE; - - *out_transform = transform; - return TRUE; -} - -static gboolean -should_have_hw_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - GList *gpus) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - CoglTexture *texture; - MetaMonitorTransform transform; - float scale; - GList *l; - - if (!gpus) - return FALSE; - - if (!cursor_sprite) - return FALSE; - - if (meta_backend_is_hw_cursors_inhibited (priv->backend)) - return FALSE; - - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - - cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - if (!cursor_renderer_gpu_data) - return FALSE; - - if (cursor_renderer_gpu_data->hw_cursor_broken) - return FALSE; - - if (!has_valid_cursor_sprite_buffer (cursor_sprite, gpu_kms)) - return FALSE; - } - - if (!crtcs_has_cursor_planes (renderer, cursor_sprite)) - return FALSE; - - texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - if (!texture) - return FALSE; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &scale)) - return FALSE; - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &transform)) - return FALSE; - - if (G_APPROX_VALUE (scale, 1.f, FLT_EPSILON) && - transform == META_MONITOR_TRANSFORM_NORMAL) - return TRUE; - else - return get_can_preprocess (cursor_sprite); - - return TRUE; -} - -static gboolean -meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); - MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer); - - priv->animation_timeout_id = 0; - meta_cursor_sprite_tick_frame (cursor_sprite); - meta_cursor_renderer_force_update (renderer); - - return G_SOURCE_REMOVE; -} - -static void -maybe_schedule_cursor_sprite_animation_frame (MetaCursorRendererNative *native, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - gboolean cursor_change; - guint delay; - - cursor_change = cursor_sprite != priv->last_cursor; - priv->last_cursor = cursor_sprite; - - if (!cursor_change && priv->animation_timeout_id) - return; - - g_clear_handle_id (&priv->animation_timeout_id, g_source_remove); - - if (cursor_sprite && meta_cursor_sprite_is_animated (cursor_sprite)) - { - delay = meta_cursor_sprite_get_current_frame_time (cursor_sprite); - - if (delay == 0) - return; - - priv->animation_timeout_id = - g_timeout_add (delay, - (GSourceFunc) meta_cursor_renderer_native_update_animation, - native); - g_source_set_name_by_id (priv->animation_timeout_id, - "[mutter] meta_cursor_renderer_native_update_animation"); - } -} - -static GList * -calculate_cursor_sprite_gpus (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *gpus = NULL; - GList *logical_monitors; - GList *l; - graphene_rect_t cursor_rect; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaRectangle logical_monitor_layout; - graphene_rect_t logical_monitor_rect; - GList *monitors, *l_mon; - - logical_monitor_layout = - meta_logical_monitor_get_layout (logical_monitor); - logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor_layout); - - if (!graphene_rect_intersection (&cursor_rect, &logical_monitor_rect, - NULL)) - continue; - - monitors = meta_logical_monitor_get_monitors (logical_monitor); - for (l_mon = monitors; l_mon; l_mon = l_mon->next) - { - MetaMonitor *monitor = l_mon->data; - MetaOutput *output = meta_monitor_get_main_output (monitor); - MetaGpu *gpu; - - gpu = meta_output_get_gpu (output); - if (gpu && !g_list_find (gpus, gpu)) - gpus = g_list_prepend (gpus, gpu); - } - } - - return gpus; -} - -static void -on_kms_update_result (const MetaKmsFeedback *kms_feedback, - gpointer user_data) -{ - MetaCursorRendererNative *cursor_renderer_native = user_data; - MetaCursorRenderer *cursor_renderer = - META_CURSOR_RENDERER (cursor_renderer_native); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - gboolean has_hw_cursor_failure = FALSE; - GList *l; - - for (l = meta_kms_feedback_get_failed_planes (kms_feedback); l; l = l->next) - { - MetaKmsPlaneFeedback *plane_feedback = l->data; - - switch (meta_kms_plane_get_plane_type (plane_feedback->plane)) - { - case META_KMS_PLANE_TYPE_CURSOR: - break; - case META_KMS_PLANE_TYPE_PRIMARY: - case META_KMS_PLANE_TYPE_OVERLAY: - continue; - } - - disable_hw_cursor_for_crtc (plane_feedback->crtc, - plane_feedback->error); - has_hw_cursor_failure = TRUE; - } - - if (has_hw_cursor_failure) - { - priv->has_hw_cursor = FALSE; - meta_cursor_renderer_force_update (cursor_renderer); - } -} - -static void -schedule_sync_position (MetaCursorRendererNative *cursor_renderer_native) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - GList *l; - - for (l = meta_backend_get_gpus (priv->backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - GList *l_crtc; - - for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l_crtc->data); - CrtcCursorData *crtc_cursor_data; - - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_cursor_data->needs_sync_position = TRUE; - } - } -} - -static gboolean -meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (priv->backend)); - g_autoptr (GList) gpus = NULL; - - if (cursor_sprite) - { - meta_cursor_sprite_realize_texture (cursor_sprite); - gpus = calculate_cursor_sprite_gpus (renderer, cursor_sprite); - realize_cursor_sprite (renderer, cursor_sprite, gpus); - } - - maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite); - - priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite, gpus); - - schedule_sync_position (native); - clutter_stage_schedule_update (stage); - - return (priv->has_hw_cursor || - !cursor_sprite || - !meta_cursor_sprite_get_cogl_texture (cursor_sprite)); -} - -static void -unset_crtc_cursor_renderer_privates (MetaGpu *gpu, - MetaDrmBuffer *buffer) -{ - GList *l; - - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data); - MetaDrmBuffer *crtc_buffer; - - crtc_buffer = meta_crtc_kms_get_cursor_renderer_private (crtc_kms); - if (buffer == crtc_buffer) - meta_crtc_kms_set_cursor_renderer_private (crtc_kms, NULL, NULL); - } -} - -static void -cursor_gpu_state_free (MetaCursorNativeGpuState *cursor_gpu_state) -{ - int i; - MetaDrmBuffer *active_buffer; - - active_buffer = get_active_cursor_sprite_buffer (cursor_gpu_state); - if (active_buffer) - unset_crtc_cursor_renderer_privates (cursor_gpu_state->gpu, - active_buffer); - - for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++) - g_clear_object (&cursor_gpu_state->buffers[i]); - g_free (cursor_gpu_state); -} - -static MetaCursorNativeGpuState * -get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms) -{ - return g_hash_table_lookup (cursor_priv->gpu_states, gpu_kms); -} - -static MetaCursorNativeGpuState * -ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativeGpuState *cursor_gpu_state; - - cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); - if (cursor_gpu_state) - return cursor_gpu_state; - - cursor_gpu_state = g_new0 (MetaCursorNativeGpuState, 1); - cursor_gpu_state->gpu = META_GPU (gpu_kms); - g_hash_table_insert (cursor_priv->gpu_states, gpu_kms, cursor_gpu_state); - - return cursor_gpu_state; -} - -static void -invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - GHashTableIter iter; - MetaCursorNativeGpuState *cursor_gpu_state; - - g_hash_table_iter_init (&iter, cursor_priv->gpu_states); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cursor_gpu_state)) - { - unsigned int pending_buffer_idx; - - pending_buffer_idx = get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - g_clear_object (&cursor_gpu_state->buffers[pending_buffer_idx]); - cursor_gpu_state->pending_buffer_state = - META_CURSOR_BUFFER_STATE_INVALIDATED; - } -} - -static void -on_cursor_sprite_texture_changed (MetaCursorSprite *cursor_sprite) -{ - invalidate_cursor_gpu_state (cursor_sprite); -} - -static void -cursor_priv_free (MetaCursorNativePrivate *cursor_priv) -{ - g_hash_table_destroy (cursor_priv->gpu_states); - g_free (cursor_priv); -} - -static MetaCursorNativePrivate * -get_cursor_priv (MetaCursorSprite *cursor_sprite) -{ - return g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite); -} - -static MetaCursorNativePrivate * -ensure_cursor_priv (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (cursor_priv) - return cursor_priv; - - cursor_priv = g_new0 (MetaCursorNativePrivate, 1); - cursor_priv->gpu_states = - g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify) cursor_gpu_state_free); - g_object_set_qdata_full (G_OBJECT (cursor_sprite), - quark_cursor_sprite, - cursor_priv, - (GDestroyNotify) cursor_priv_free); - - g_signal_connect (cursor_sprite, "texture-changed", - G_CALLBACK (on_cursor_sprite_texture_changed), NULL); - - unset_can_preprocess (cursor_sprite); - - return cursor_priv; -} - -static void -load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native, - MetaGpuKms *gpu_kms, - 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; - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - struct gbm_device *gbm_device; - - cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - if (!cursor_renderer_gpu_data) - return; - - cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width; - cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height; - - if (width > cursor_width || height > cursor_height) - { - meta_warning ("Invalid theme cursor size (must be at most %ux%u)", - (unsigned int)cursor_width, (unsigned int)cursor_height); - return; - } - - gbm_device = meta_gbm_device_from_gpu (gpu_kms); - if (gbm_device_is_format_supported (gbm_device, gbm_format, - GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) - { - MetaBackendNative *backend_native = META_BACKEND_NATIVE (priv->backend); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (backend_native); - g_autoptr (MetaDeviceFile) device_file = NULL; - struct gbm_bo *bo; - uint8_t buf[4 * cursor_width * cursor_height]; - uint i; - g_autoptr (GError) error = NULL; - MetaDrmBufferGbm *buffer_gbm; - - device_file = meta_device_pool_open (device_pool, - meta_gpu_kms_get_file_path (gpu_kms), - META_DEVICE_FILE_FLAG_TAKE_CONTROL, - &error); - if (!device_file) - { - g_warning ("Failed to open '%s' for updating the cursor: %s", - meta_gpu_kms_get_file_path (gpu_kms), - error->message); - return; - } - - bo = gbm_bo_create (gbm_device, cursor_width, cursor_height, - gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); - if (!bo) - { - meta_warning ("Failed to allocate HW cursor buffer"); - return; - } - - memset (buf, 0, sizeof(buf)); - for (i = 0; i < height; i++) - memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4); - if (gbm_bo_write (bo, buf, cursor_width * cursor_height * 4) != 0) - { - meta_warning ("Failed to write cursors buffer data: %s", - g_strerror (errno)); - gbm_bo_destroy (bo); - return; - } - - buffer_gbm = meta_drm_buffer_gbm_new_take (device_file, bo, FALSE, &error); - if (!buffer_gbm) - { - meta_warning ("Failed to create DRM buffer wrapper: %s", - error->message); - gbm_bo_destroy (bo); - return; - } - - set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms, - META_DRM_BUFFER (buffer_gbm)); - } - else - { - meta_warning ("HW cursor for format %d not supported", gbm_format); - } -} - -static gboolean -is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativePrivate *cursor_priv; - MetaCursorNativeGpuState *cursor_gpu_state; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (!cursor_priv) - return FALSE; - - cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); - if (!cursor_gpu_state) - return FALSE; - - switch (cursor_gpu_state->pending_buffer_state) - { - case META_CURSOR_BUFFER_STATE_SET: - case META_CURSOR_BUFFER_STATE_NONE: - return TRUE; - case META_CURSOR_BUFFER_STATE_INVALIDATED: - return FALSE; - } - - g_assert_not_reached (); - return FALSE; -} - -static gboolean -is_cursor_scale_and_transform_valid (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaMonitorTransform transform; - float scale; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &scale)) - return FALSE; - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &transform)) - return FALSE; - - return (scale == get_current_relative_scale (cursor_sprite) && - transform == get_current_relative_transform (cursor_sprite)); -} - -static cairo_surface_t * -scale_and_transform_cursor_sprite_cpu (uint8_t *pixels, - int width, - int height, - int rowstride, - float scale, - MetaMonitorTransform transform) -{ - cairo_t *cr; - cairo_surface_t *source_surface; - cairo_surface_t *target_surface; - int image_width; - int image_height; - - image_width = ceilf (width * scale); - image_height = ceilf (height * scale); - - target_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - image_width, - image_height); - - cr = cairo_create (target_surface); - if (transform != META_MONITOR_TRANSFORM_NORMAL) - { - cairo_translate (cr, 0.5 * image_width, 0.5 * image_height); - switch (transform) - { - case META_MONITOR_TRANSFORM_90: - cairo_rotate (cr, M_PI * 1.5); - break; - case META_MONITOR_TRANSFORM_180: - cairo_rotate (cr, M_PI); - break; - case META_MONITOR_TRANSFORM_270: - cairo_rotate (cr, M_PI * 0.5); - break; - case META_MONITOR_TRANSFORM_FLIPPED: - cairo_scale (cr, 1, -1); - break; - case META_MONITOR_TRANSFORM_FLIPPED_90: - cairo_rotate (cr, M_PI * 1.5); - cairo_scale (cr, -1, 1); - break; - case META_MONITOR_TRANSFORM_FLIPPED_180: - cairo_rotate (cr, M_PI); - cairo_scale (cr, 1, -1); - break; - case META_MONITOR_TRANSFORM_FLIPPED_270: - cairo_rotate (cr, M_PI * 0.5); - cairo_scale (cr, -1, 1); - break; - case META_MONITOR_TRANSFORM_NORMAL: - g_assert_not_reached (); - } - cairo_translate (cr, -0.5 * image_width, -0.5 * image_height); - } - cairo_scale (cr, scale, scale); - - source_surface = cairo_image_surface_create_for_data (pixels, - CAIRO_FORMAT_ARGB32, - width, - height, - rowstride); - - cairo_set_source_surface (cr, source_surface, 0, 0); - cairo_paint (cr); - cairo_destroy (cr); - cairo_surface_destroy (source_surface); - - return target_surface; -} - -static void -load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native, - MetaGpuKms *gpu_kms, - MetaCursorSprite *cursor_sprite, - float relative_scale, - MetaMonitorTransform relative_transform, - uint8_t *data, - int width, - int height, - int rowstride, - uint32_t gbm_format) -{ - if (!G_APPROX_VALUE (relative_scale, 1.f, FLT_EPSILON) || - relative_transform != META_MONITOR_TRANSFORM_NORMAL) - { - cairo_surface_t *surface; - - surface = scale_and_transform_cursor_sprite_cpu (data, - width, - height, - rowstride, - relative_scale, - relative_transform); - - load_cursor_sprite_gbm_buffer_for_gpu (native, - gpu_kms, - cursor_sprite, - cairo_image_surface_get_data (surface), - cairo_image_surface_get_width (surface), - cairo_image_surface_get_width (surface), - cairo_image_surface_get_stride (surface), - gbm_format); - - cairo_surface_destroy (surface); - } - else - { - load_cursor_sprite_gbm_buffer_for_gpu (native, - gpu_kms, - cursor_sprite, - data, - width, - height, - rowstride, - gbm_format); - } -} - -#ifdef HAVE_WAYLAND -static void -realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, - MetaGpuKms *gpu_kms, - MetaCursorSpriteWayland *sprite_wayland) -{ - MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_wayland); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - uint64_t cursor_width, cursor_height; - CoglTexture *texture; - uint width, height; - MetaWaylandBuffer *buffer; - struct wl_resource *buffer_resource; - struct wl_shm_buffer *shm_buffer; - - cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) - return; - - if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) && - is_cursor_scale_and_transform_valid (renderer, cursor_sprite)) - return; - - buffer = meta_cursor_sprite_wayland_get_buffer (sprite_wayland); - if (!buffer) - return; - - buffer_resource = meta_wayland_buffer_get_resource (buffer); - if (!buffer_resource) - return; - - ensure_cursor_priv (cursor_sprite); - - shm_buffer = wl_shm_buffer_get (buffer_resource); - if (shm_buffer) - { - int rowstride = wl_shm_buffer_get_stride (shm_buffer); - uint8_t *buffer_data; - float relative_scale; - MetaMonitorTransform relative_transform; - uint32_t gbm_format; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &relative_scale)) - { - unset_can_preprocess (cursor_sprite); - return; - } - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &relative_transform)) - { - unset_can_preprocess (cursor_sprite); - return; - } - - set_can_preprocess (cursor_sprite, - relative_scale, - relative_transform); - - wl_shm_buffer_begin_access (shm_buffer); - buffer_data = wl_shm_buffer_get_data (shm_buffer); - - width = wl_shm_buffer_get_width (shm_buffer); - height = wl_shm_buffer_get_height (shm_buffer); - - switch (wl_shm_buffer_get_format (shm_buffer)) - { - case WL_SHM_FORMAT_ARGB8888: - gbm_format = GBM_FORMAT_ARGB8888; - break; - case WL_SHM_FORMAT_XRGB8888: - gbm_format = GBM_FORMAT_XRGB8888; - break; - default: - g_warn_if_reached (); - gbm_format = GBM_FORMAT_ARGB8888; - } - - load_scaled_and_transformed_cursor_sprite (native, - gpu_kms, - cursor_sprite, - relative_scale, - relative_transform, - buffer_data, - width, - height, - rowstride, - gbm_format); - - wl_shm_buffer_end_access (shm_buffer); - } - else - { - MetaBackendNative *backend_native = META_BACKEND_NATIVE (priv->backend); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (backend_native); - g_autoptr (MetaDeviceFile) device_file = NULL; - struct gbm_device *gbm_device; - struct gbm_bo *bo; - g_autoptr (GError) error = NULL; - MetaDrmBufferGbm *buffer_gbm; - - device_file = meta_device_pool_open (device_pool, - meta_gpu_kms_get_file_path (gpu_kms), - META_DEVICE_FILE_FLAG_TAKE_CONTROL, - &error); - if (!device_file) - { - g_warning ("Failed to open '%s' for updating the cursor: %s", - meta_gpu_kms_get_file_path (gpu_kms), - error->message); - return; - } - - /* 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. */ - cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width; - cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height; - - texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - width = cogl_texture_get_width (texture); - height = cogl_texture_get_height (texture); - - if (width != cursor_width || height != cursor_height) - { - meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors"); - return; - } - - gbm_device = meta_gbm_device_from_gpu (gpu_kms); - bo = gbm_bo_import (gbm_device, - GBM_BO_IMPORT_WL_BUFFER, - buffer, - GBM_BO_USE_CURSOR); - if (!bo) - { - meta_warning ("Importing HW cursor from wl_buffer failed"); - return; - } - - unset_can_preprocess (cursor_sprite); - - buffer_gbm = meta_drm_buffer_gbm_new_take (device_file, bo, FALSE, &error); - if (!buffer_gbm) - { - meta_warning ("Failed to create DRM buffer wrapper: %s", - error->message); - gbm_bo_destroy (bo); - return; - } - - set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms, - META_DRM_BUFFER (buffer_gbm)); - } -} -#endif - -static void -realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer, - MetaGpuKms *gpu_kms, - MetaCursorSpriteXcursor *sprite_xcursor) -{ - MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor); - XcursorImage *xc_image; - float relative_scale; - MetaMonitorTransform relative_transform; - - ensure_cursor_priv (cursor_sprite); - - cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) - return; - - if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) && - is_cursor_scale_and_transform_valid (renderer, cursor_sprite)) - return; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &relative_scale)) - { - unset_can_preprocess (cursor_sprite); - return; - } - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &relative_transform)) - { - unset_can_preprocess (cursor_sprite); - return; - } - - set_can_preprocess (cursor_sprite, - relative_scale, - relative_transform); - - xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor); - - load_scaled_and_transformed_cursor_sprite (native, - gpu_kms, - cursor_sprite, - relative_scale, - relative_transform, - (uint8_t *) xc_image->pixels, - xc_image->width, - xc_image->height, - xc_image->width * 4, - GBM_FORMAT_ARGB8888); -} - -static void -realize_cursor_sprite_for_gpu (MetaCursorRenderer *renderer, - MetaGpuKms *gpu_kms, - MetaCursorSprite *cursor_sprite) -{ - if (META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite)) - { - MetaCursorSpriteXcursor *sprite_xcursor = - META_CURSOR_SPRITE_XCURSOR (cursor_sprite); - - realize_cursor_sprite_from_xcursor_for_gpu (renderer, - gpu_kms, - sprite_xcursor); - } -#ifdef HAVE_WAYLAND - else if (META_IS_CURSOR_SPRITE_WAYLAND (cursor_sprite)) - { - MetaCursorSpriteWayland *sprite_wayland = - META_CURSOR_SPRITE_WAYLAND (cursor_sprite); - - realize_cursor_sprite_from_wl_buffer_for_gpu (renderer, - gpu_kms, - sprite_wayland); - } -#endif -} - -static void -realize_cursor_sprite (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - GList *gpus) -{ - GList *l; - - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - - realize_cursor_sprite_for_gpu (renderer, gpu_kms, cursor_sprite); - } -} - -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; - - quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native"); - quark_cursor_renderer_native_gpu_data = - g_quark_from_static_string ("-meta-cursor-renderer-native-gpu-data"); -} - -static void -force_update_hw_cursor (MetaCursorRendererNative *native) -{ - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - GList *l; - - for (l = meta_backend_get_gpus (priv->backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - GList *l_crtc; - - for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l_crtc->data); - CrtcCursorData *crtc_cursor_data; - - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_cursor_data->hw_state_invalidated = TRUE; - } - } - - meta_cursor_renderer_force_update (renderer); -} - -static void -on_monitors_changed (MetaMonitorManager *monitors, - MetaCursorRendererNative *native) -{ - force_update_hw_cursor (native); -} - -static void -init_hw_cursor_support_for_gpu (MetaGpuKms *gpu_kms) -{ - MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - struct gbm_device *gbm_device; - uint64_t width, height; - - gbm_device = meta_gbm_device_from_gpu (gpu_kms); - if (!gbm_device) - return; - - cursor_renderer_gpu_data = - meta_create_cursor_renderer_native_gpu_data (gpu_kms); - - if (!meta_kms_device_get_cursor_size (kms_device, &width, &height)) - { - width = 64; - height = 64; - } - - cursor_renderer_gpu_data->cursor_width = width; - cursor_renderer_gpu_data->cursor_height = height; -} - -static void -on_gpu_added_for_cursor (MetaBackend *backend, - MetaGpuKms *gpu_kms) -{ - init_hw_cursor_support_for_gpu (gpu_kms); -} - -static void -init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - GList *gpus; - GList *l; - - gpus = meta_backend_get_gpus (priv->backend); - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - - init_hw_cursor_support_for_gpu (gpu_kms); - } -} - -MetaCursorRendererNative * -meta_cursor_renderer_native_new (MetaBackend *backend, - ClutterInputDevice *device) -{ - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCursorRendererNative *cursor_renderer_native; - MetaCursorRendererNativePrivate *priv; - - cursor_renderer_native = g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, - "backend", backend, - "device", device, - NULL); - priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - - g_signal_connect_object (monitor_manager, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed), - cursor_renderer_native, 0); - g_signal_connect (backend, "gpu-added", - G_CALLBACK (on_gpu_added_for_cursor), NULL); - - priv->backend = backend; - - init_hw_cursor_support (cursor_renderer_native); - - return cursor_renderer_native; -} - -static void -meta_cursor_renderer_native_init (MetaCursorRendererNative *native) -{ -} diff --git a/src/backends/native/meta-cursor-renderer-native.h b/src/backends/native/meta-cursor-renderer-native.h deleted file mode 100644 index 5113b96ce..000000000 --- a/src/backends/native/meta-cursor-renderer-native.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- 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 <jstpierre@mecheye.net> - */ - -#ifndef META_CURSOR_RENDERER_NATIVE_H -#define META_CURSOR_RENDERER_NATIVE_H - -#include "backends/meta-cursor-renderer.h" -#include "meta/meta-backend.h" - -#define META_TYPE_CURSOR_RENDERER_NATIVE (meta_cursor_renderer_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCursorRendererNative, meta_cursor_renderer_native, - META, CURSOR_RENDERER_NATIVE, - MetaCursorRenderer) - -void meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native, - MetaRendererView *view); - -MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend, - ClutterInputDevice *device); - -#endif /* META_CURSOR_RENDERER_NATIVE_H */ diff --git a/src/backends/native/meta-device-pool-private.h b/src/backends/native/meta-device-pool-private.h deleted file mode 100644 index 06a43f6f4..000000000 --- a/src/backends/native/meta-device-pool-private.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat, Inc. - * - * 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. - */ - -#ifndef META_DEVICE_POOL_PRIVATE_H -#define META_DEVICE_POOL_PRIVATE_H - -#include <glib-object.h> - -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-launcher.h" - -#define META_TYPE_DEVICE_POOL (meta_device_pool_get_type ()) -G_DECLARE_FINAL_TYPE (MetaDevicePool, meta_device_pool, - META, DEVICE_POOL, - GObject) - -MetaDevicePool * meta_device_pool_new (MetaLauncher *launcher); - -#endif /* META_DEVICE_POOL_PRIVATE_H */ diff --git a/src/backends/native/meta-device-pool.c b/src/backends/native/meta-device-pool.c deleted file mode 100644 index 8bbbe3e34..000000000 --- a/src/backends/native/meta-device-pool.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (C) 2013-2021 Red Hat, Inc. - * - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-device-pool-private.h" - -#include <fcntl.h> -#include <gio/gunixfdlist.h> -#include <sys/stat.h> -#include <sys/stat.h> -#include <sys/sysmacros.h> -#include <sys/types.h> - -#include "backends/native/meta-launcher.h" -#include "meta/util.h" - -#include "meta-dbus-login1.h" - -struct _MetaDeviceFile -{ - MetaDevicePool *pool; - - grefcount ref_count; - - char *path; - int major; - int minor; - int fd; - MetaDeviceFileFlags flags; - uint32_t tags[META_DEVICE_FILE_N_TAGS]; -}; - -struct _MetaDevicePool -{ - GObject parent; - - MetaDbusLogin1Session *session_proxy; - - GMutex mutex; - - GList *files; -}; - -G_DEFINE_TYPE (MetaDevicePool, meta_device_pool, G_TYPE_OBJECT) - -static void -release_device_file (MetaDevicePool *pool, - MetaDeviceFile *file); - -static MetaDeviceFile * -meta_device_file_new (MetaDevicePool *pool, - const char *path, - int major, - int minor, - int fd, - MetaDeviceFileFlags flags) -{ - MetaDeviceFile *file; - - file = g_new0 (MetaDeviceFile, 1); - - file->pool = pool; - g_ref_count_init (&file->ref_count); - - file->path = g_strdup (path); - file->major = major; - file->minor = minor; - file->fd = fd; - file->flags = flags; - - return file; -} - -static void -meta_device_file_free (MetaDeviceFile *file) -{ - g_free (file->path); - g_free (file); -} - -int -meta_device_file_get_fd (MetaDeviceFile *device_file) -{ - g_assert (!g_ref_count_compare (&device_file->ref_count, 0)); - - return device_file->fd; -} - -const char * -meta_device_file_get_path (MetaDeviceFile *device_file) -{ - return device_file->path; -} - -void -meta_device_file_tag (MetaDeviceFile *device_file, - MetaDeviceFileTags tag, - uint32_t value) -{ - device_file->tags[tag] |= value; -} - -uint32_t -meta_device_file_has_tag (MetaDeviceFile *device_file, - MetaDeviceFileTags tag, - uint32_t value) -{ - return (device_file->tags[tag] & value) == value; -} - -static MetaDeviceFile * -meta_device_file_acquire_locked (MetaDeviceFile *file) -{ - g_ref_count_inc (&file->ref_count); - return file; -} - -MetaDeviceFile * -meta_device_file_acquire (MetaDeviceFile *file) -{ - g_mutex_lock (&file->pool->mutex); - meta_topic (META_DEBUG_BACKEND, "Acquiring device file '%s'", file->path); - meta_device_file_acquire_locked (file); - g_mutex_unlock (&file->pool->mutex); - - return file; -} - -void -meta_device_file_release (MetaDeviceFile *file) -{ - g_warn_if_fail (file->fd != -1); - - release_device_file (file->pool, file); -} - -MetaDevicePool * -meta_device_file_get_pool (MetaDeviceFile *device_file) -{ - return device_file->pool; -} - -static MetaDeviceFile * -find_device_file_from_path (MetaDevicePool *pool, - const char *path) -{ - GList *l; - - for (l = pool->files; l; l = l->next) - { - MetaDeviceFile *file = l->data; - - if (g_strcmp0 (file->path, path) == 0) - return file; - } - - return NULL; -} - -static gboolean -take_device (MetaDbusLogin1Session *session_proxy, - int dev_major, - int dev_minor, - int *out_fd, - GCancellable *cancellable, - GError **error) -{ - g_autoptr (GVariant) fd_variant = NULL; - g_autoptr (GUnixFDList) fd_list = NULL; - int fd = -1; - - if (!meta_dbus_login1_session_call_take_device_sync (session_proxy, - dev_major, - dev_minor, - NULL, - &fd_variant, - NULL, /* paused */ - &fd_list, - cancellable, - error)) - return FALSE; - - fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error); - if (fd == -1) - return FALSE; - - *out_fd = fd; - return TRUE; -} - -static gboolean -get_device_info_from_path (const char *path, - int *out_major, - int *out_minor) -{ - int ret; - struct stat st; - - ret = stat (path, &st); - if (ret < 0 || !S_ISCHR (st.st_mode)) - return FALSE; - - *out_major = major (st.st_rdev); - *out_minor = minor (st.st_rdev); - return TRUE; -} - -MetaDeviceFile * -meta_device_pool_open (MetaDevicePool *pool, - const char *path, - MetaDeviceFileFlags flags, - GError **error) -{ - g_autoptr (GMutexLocker) locker = NULL; - MetaDeviceFile *file; - int major = -1, minor = -1; - int fd; - - locker = g_mutex_locker_new (&pool->mutex); - - file = find_device_file_from_path (pool, path); - if (file) - { - g_warn_if_fail (file->flags == flags); - meta_device_file_acquire_locked (file); - return file; - } - - if (flags & META_DEVICE_FILE_FLAG_TAKE_CONTROL) - { - meta_topic (META_DEBUG_BACKEND, - "Opening and taking control of device file '%s'", - path); - - if (!pool->session_proxy) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Can't take control without logind session"); - return NULL; - } - - if (!get_device_info_from_path (path, &major, &minor)) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Could not get device info for path %s: %m", path); - return NULL; - } - - if (!take_device (pool->session_proxy, major, minor, &fd, NULL, error)) - return NULL; - } - else - { - int open_flags; - - meta_topic (META_DEBUG_BACKEND, - "Opening device file '%s'", - path); - - if (flags & META_DEVICE_FILE_FLAG_READ_ONLY) - open_flags = O_RDONLY; - else - open_flags = O_RDWR; - open_flags |= O_CLOEXEC; - - do - { - fd = open (path, open_flags); - } - while (fd == -1 && errno == EINTR); - - if (fd == -1) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to open device '%s': %s", - path, g_strerror (errno)); - return NULL; - } - } - - file = meta_device_file_new (pool, path, major, minor, fd, flags); - pool->files = g_list_prepend (pool->files, file); - - return file; -} - -static void -release_device_file (MetaDevicePool *pool, - MetaDeviceFile *file) -{ - g_autoptr (GMutexLocker) locker = NULL; - g_autoptr (GError) error = NULL; - - locker = g_mutex_locker_new (&pool->mutex); - - meta_topic (META_DEBUG_BACKEND, "Releasing device file '%s'", file->path); - - if (!g_ref_count_dec (&file->ref_count)) - return; - - pool->files = g_list_remove (pool->files, file); - - if (file->flags & META_DEVICE_FILE_FLAG_TAKE_CONTROL) - { - MetaDbusLogin1Session *session_proxy; - - meta_topic (META_DEBUG_BACKEND, - "Releasing control of and closing device file '%s'", - file->path); - - session_proxy = pool->session_proxy; - if (!meta_dbus_login1_session_call_release_device_sync (session_proxy, - file->major, - file->minor, - NULL, &error)) - { - g_warning ("Could not release device '%s' (%d,%d): %s", - file->path, - file->major, file->minor, - error->message); - } - } - else - { - meta_topic (META_DEBUG_BACKEND, - "Closing device file '%s'", - file->path); - } - - close (file->fd); - - meta_device_file_free (file); -} - -MetaDevicePool * -meta_device_pool_new (MetaLauncher *launcher) -{ - MetaDevicePool *pool; - - pool = g_object_new (META_TYPE_DEVICE_POOL, NULL); - - if (launcher) - pool->session_proxy = meta_launcher_get_session_proxy (launcher); - - return pool; -} - -static void -meta_device_pool_finalize (GObject *object) -{ - MetaDevicePool *pool = META_DEVICE_POOL (object); - - g_mutex_clear (&pool->mutex); - g_warn_if_fail (!pool->files); - - G_OBJECT_CLASS (meta_device_pool_parent_class)->finalize (object); -} - -static void -meta_device_pool_init (MetaDevicePool *pool) -{ - g_mutex_init (&pool->mutex); -} - -static void -meta_device_pool_class_init (MetaDevicePoolClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_device_pool_finalize; -} diff --git a/src/backends/native/meta-device-pool.h b/src/backends/native/meta-device-pool.h deleted file mode 100644 index 0e9653bd6..000000000 --- a/src/backends/native/meta-device-pool.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat, Inc. - * - * 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. - */ - -#ifndef META_DEVICE_POOL_H -#define META_DEVICE_POOL_H - -#include <glib-object.h> -#include <stdint.h> - -typedef enum _MetaDeviceFileFlags -{ - META_DEVICE_FILE_FLAG_NONE = 0, - META_DEVICE_FILE_FLAG_TAKE_CONTROL = 1 << 0, - META_DEVICE_FILE_FLAG_READ_ONLY = 1 << 1, -} MetaDeviceFileFlags; - -typedef enum _MetaDeviceFileTags -{ - META_DEVICE_FILE_TAG_KMS, - - META_DEVICE_FILE_N_TAGS, -} MetaDeviceFileTags; - -typedef struct _MetaDeviceFile MetaDeviceFile; -typedef struct _MetaDevicePool MetaDevicePool; - -int meta_device_file_get_fd (MetaDeviceFile *device_file); - -const char * meta_device_file_get_path (MetaDeviceFile *device_file); - -void meta_device_file_tag (MetaDeviceFile *device_file, - MetaDeviceFileTags tag, - uint32_t value); - -uint32_t meta_device_file_has_tag (MetaDeviceFile *device_file, - MetaDeviceFileTags tag, - uint32_t value); - -MetaDeviceFile * meta_device_file_acquire (MetaDeviceFile *file); - -void meta_device_file_release (MetaDeviceFile *device_file); - -MetaDevicePool * meta_device_file_get_pool (MetaDeviceFile *device_file); - -MetaDeviceFile * meta_device_pool_open (MetaDevicePool *pool, - const char *path, - MetaDeviceFileFlags flags, - GError **error); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaDeviceFile, meta_device_file_release) - -#endif /* META_DEVICE_FILE_POOL_H */ diff --git a/src/backends/native/meta-drm-buffer-dumb.c b/src/backends/native/meta-drm-buffer-dumb.c deleted file mode 100644 index d2fcad2f0..000000000 --- a/src/backends/native/meta-drm-buffer-dumb.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * Copyright (C) 2018 Canonical Ltd. - * - * 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. - * - */ - -#include "config.h" - -#include "backends/native/meta-drm-buffer-dumb.h" - -#include <gio/gio.h> -#include <xf86drm.h> -#include <fcntl.h> -#include <sys/mman.h> - -#include "backends/native/meta-device-pool.h" - -struct _MetaDrmBufferDumb -{ - MetaDrmBuffer parent; - - uint32_t handle; - void *map; - uint64_t map_size; - int width; - int height; - int stride_bytes; - uint32_t drm_format; - int dmabuf_fd; -}; - -G_DEFINE_TYPE (MetaDrmBufferDumb, meta_drm_buffer_dumb, META_TYPE_DRM_BUFFER) - -static int -meta_drm_buffer_dumb_get_width (MetaDrmBuffer *buffer) -{ - MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer); - - return buffer_dumb->width; -} - -static int -meta_drm_buffer_dumb_get_height (MetaDrmBuffer *buffer) -{ - MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer); - - return buffer_dumb->height; -} - -static int -meta_drm_buffer_dumb_get_stride (MetaDrmBuffer *buffer) -{ - MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer); - - return buffer_dumb->stride_bytes; -} - -static uint32_t -meta_drm_buffer_dumb_get_format (MetaDrmBuffer *buffer) -{ - MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer); - - return buffer_dumb->drm_format; -} - -static int -handle_to_dmabuf_fd (MetaDrmBufferDumb *buffer_dumb, - GError **error) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb); - MetaDeviceFile *device_file; - int fd; - int ret; - int dmabuf_fd; - - device_file = meta_drm_buffer_get_device_file (buffer); - fd = meta_device_file_get_fd (device_file); - - ret = drmPrimeHandleToFD (fd, buffer_dumb->handle, DRM_CLOEXEC, - &dmabuf_fd); - if (ret) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmPrimeHandleToFd: %s", g_strerror (-ret)); - return -1; - } - - return dmabuf_fd; -} - -int -meta_drm_buffer_dumb_ensure_dmabuf_fd (MetaDrmBufferDumb *buffer_dumb, - GError **error) -{ - if (buffer_dumb->dmabuf_fd != -1) - return buffer_dumb->dmabuf_fd; - - buffer_dumb->dmabuf_fd = handle_to_dmabuf_fd (buffer_dumb, error); - return buffer_dumb->dmabuf_fd; -} - -void * -meta_drm_buffer_dumb_get_data (MetaDrmBufferDumb *buffer_dumb) -{ - return buffer_dumb->map; -} - -static gboolean -init_dumb_buffer (MetaDrmBufferDumb *buffer_dumb, - int width, - int height, - uint32_t format, - GError **error) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb); - MetaDeviceFile *device_file; - int fd; - struct drm_mode_create_dumb create_arg; - struct drm_mode_destroy_dumb destroy_arg; - struct drm_mode_map_dumb map_arg; - void *map; - MetaDrmFbArgs fb_args; - - device_file = meta_drm_buffer_get_device_file (buffer); - fd = meta_device_file_get_fd (device_file); - - create_arg = (struct drm_mode_create_dumb) { - .bpp = 32, /* RGBX8888 */ - .width = width, - .height = height - }; - if (drmIoctl (fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg) != 0) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to create dumb drm buffer: %s", - g_strerror (errno)); - goto err_ioctl; - } - - fb_args = (MetaDrmFbArgs) { - .width = width, - .height = height, - .format = format, - .handles = { create_arg.handle }, - .strides = { create_arg.pitch }, - }; - if (!meta_drm_buffer_ensure_fb_id (buffer, FALSE, &fb_args, error)) - goto err_add_fb; - - map_arg = (struct drm_mode_map_dumb) { - .handle = create_arg.handle - }; - if (drmIoctl (fd, DRM_IOCTL_MODE_MAP_DUMB, - &map_arg) != 0) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to map dumb drm buffer: %s", - g_strerror (errno)); - goto err_map_dumb; - } - - map = mmap (NULL, create_arg.size, PROT_WRITE, MAP_SHARED, - fd, map_arg.offset); - if (map == MAP_FAILED) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to mmap dumb drm buffer memory: %s", - g_strerror (errno)); - goto err_mmap; - } - - buffer_dumb->handle = create_arg.handle; - buffer_dumb->map = map; - buffer_dumb->map_size = create_arg.size; - buffer_dumb->width = width; - buffer_dumb->height = height; - buffer_dumb->stride_bytes = create_arg.pitch; - buffer_dumb->drm_format = format; - - return TRUE; - -err_mmap: -err_map_dumb: -err_add_fb: - destroy_arg = (struct drm_mode_destroy_dumb) { - .handle = create_arg.handle - }; - drmIoctl (fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); - -err_ioctl: - return FALSE; -} - -MetaDrmBufferDumb * -meta_drm_buffer_dumb_new (MetaDeviceFile *device_file, - int width, - int height, - uint32_t format, - GError **error) -{ - MetaDrmBufferDumb *buffer_dumb; - - buffer_dumb = g_object_new (META_TYPE_DRM_BUFFER_DUMB, - "device-file", device_file, - NULL); - - if (!init_dumb_buffer (buffer_dumb, width, height, format, error)) - { - g_object_unref (buffer_dumb); - return NULL; - } - - return buffer_dumb; -} - -static void -destroy_dumb_buffer (MetaDrmBufferDumb *buffer_dumb) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb); - MetaDeviceFile *device_file; - int fd; - struct drm_mode_destroy_dumb destroy_arg; - - device_file = meta_drm_buffer_get_device_file (buffer); - fd = meta_device_file_get_fd (device_file); - - munmap (buffer_dumb->map, buffer_dumb->map_size); - - destroy_arg = (struct drm_mode_destroy_dumb) { - .handle = buffer_dumb->handle - }; - drmIoctl (fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); - - if (buffer_dumb->dmabuf_fd != -1) - close (buffer_dumb->dmabuf_fd); -} - -static void -meta_drm_buffer_dumb_finalize (GObject *object) -{ - MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (object); - - if (buffer_dumb->handle) - destroy_dumb_buffer (buffer_dumb); - - G_OBJECT_CLASS (meta_drm_buffer_dumb_parent_class)->finalize (object); -} - -static void -meta_drm_buffer_dumb_init (MetaDrmBufferDumb *buffer_dumb) -{ - buffer_dumb->dmabuf_fd = -1; -} - -static void -meta_drm_buffer_dumb_class_init (MetaDrmBufferDumbClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaDrmBufferClass *buffer_class = META_DRM_BUFFER_CLASS (klass); - - object_class->finalize = meta_drm_buffer_dumb_finalize; - - buffer_class->get_width = meta_drm_buffer_dumb_get_width; - buffer_class->get_height = meta_drm_buffer_dumb_get_height; - buffer_class->get_stride = meta_drm_buffer_dumb_get_stride; - buffer_class->get_format = meta_drm_buffer_dumb_get_format; -} diff --git a/src/backends/native/meta-drm-buffer-dumb.h b/src/backends/native/meta-drm-buffer-dumb.h deleted file mode 100644 index afc14660b..000000000 --- a/src/backends/native/meta-drm-buffer-dumb.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2018 Canonical Ltd. - * Copyright (C) 2019 Red Hat Inc. - * - * 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. - * - */ - -#ifndef META_DRM_BUFFER_DUMB_H -#define META_DRM_BUFFER_DUMB_H - -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-drm-buffer-private.h" - -#define META_TYPE_DRM_BUFFER_DUMB (meta_drm_buffer_dumb_get_type ()) -G_DECLARE_FINAL_TYPE (MetaDrmBufferDumb, - meta_drm_buffer_dumb, - META, DRM_BUFFER_DUMB, - MetaDrmBuffer) - -MetaDrmBufferDumb * meta_drm_buffer_dumb_new (MetaDeviceFile *device, - int width, - int height, - uint32_t format, - GError **error); - -int meta_drm_buffer_dumb_ensure_dmabuf_fd (MetaDrmBufferDumb *buffer_dumb, - GError **error); - -void * meta_drm_buffer_dumb_get_data (MetaDrmBufferDumb *buffer_dumb); - -#endif /* META_DRM_BUFFER_DUMB_H */ diff --git a/src/backends/native/meta-drm-buffer-gbm.c b/src/backends/native/meta-drm-buffer-gbm.c deleted file mode 100644 index f011afaca..000000000 --- a/src/backends/native/meta-drm-buffer-gbm.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * Copyright (C) 2018 Canonical Ltd. - * - * 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. - * - */ - -#include "config.h" - -#include "backends/native/meta-drm-buffer-gbm.h" - -#include <drm_fourcc.h> -#include <errno.h> -#include <gio/gio.h> -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "backends/meta-backend-private.h" -#include "backends/native/meta-cogl-utils.h" -#include "backends/native/meta-drm-buffer-private.h" - -struct _MetaDrmBufferGbm -{ - MetaDrmBuffer parent; - - struct gbm_surface *surface; - - struct gbm_bo *bo; -}; - -static void -cogl_scanout_iface_init (CoglScanoutInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaDrmBufferGbm, meta_drm_buffer_gbm, META_TYPE_DRM_BUFFER, - G_IMPLEMENT_INTERFACE (COGL_TYPE_SCANOUT, - cogl_scanout_iface_init)) - -struct gbm_bo * -meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm) -{ - return buffer_gbm->bo; -} - -static int -meta_drm_buffer_gbm_get_width (MetaDrmBuffer *buffer) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer); - - return gbm_bo_get_width (buffer_gbm->bo); -} - -static int -meta_drm_buffer_gbm_get_height (MetaDrmBuffer *buffer) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer); - - return gbm_bo_get_height (buffer_gbm->bo); -} - -static int -meta_drm_buffer_gbm_get_stride (MetaDrmBuffer *buffer) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer); - - return gbm_bo_get_stride (buffer_gbm->bo); -} - -static uint32_t -meta_drm_buffer_gbm_get_format (MetaDrmBuffer *buffer) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer); - - return gbm_bo_get_format (buffer_gbm->bo); -} - -static gboolean -init_fb_id (MetaDrmBufferGbm *buffer_gbm, - struct gbm_bo *bo, - gboolean use_modifiers, - GError **error) -{ - MetaDrmFbArgs fb_args = { 0, }; - - if (gbm_bo_get_handle_for_plane (bo, 0).s32 == -1) - { - /* Failed to fetch handle to plane, falling back to old method */ - fb_args.strides[0] = gbm_bo_get_stride (bo); - fb_args.handles[0] = gbm_bo_get_handle (bo).u32; - fb_args.offsets[0] = 0; - fb_args.modifiers[0] = DRM_FORMAT_MOD_INVALID; - } - else - { - int i; - - for (i = 0; i < gbm_bo_get_plane_count (bo); i++) - { - fb_args.strides[i] = gbm_bo_get_stride_for_plane (bo, i); - fb_args.handles[i] = gbm_bo_get_handle_for_plane (bo, i).u32; - fb_args.offsets[i] = gbm_bo_get_offset (bo, i); - fb_args.modifiers[i] = gbm_bo_get_modifier (bo); - } - } - - fb_args.width = gbm_bo_get_width (bo); - fb_args.height = gbm_bo_get_height (bo); - fb_args.format = gbm_bo_get_format (bo); - - if (!meta_drm_buffer_ensure_fb_id (META_DRM_BUFFER (buffer_gbm), - use_modifiers, &fb_args, error)) - return FALSE; - - return TRUE; -} - -static gboolean -lock_front_buffer (MetaDrmBufferGbm *buffer_gbm, - gboolean use_modifiers, - GError **error) -{ - buffer_gbm->bo = gbm_surface_lock_front_buffer (buffer_gbm->surface); - if (!buffer_gbm->bo) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "gbm_surface_lock_front_buffer failed"); - return FALSE; - } - - return init_fb_id (buffer_gbm, buffer_gbm->bo, use_modifiers, error); -} - -MetaDrmBufferGbm * -meta_drm_buffer_gbm_new_lock_front (MetaDeviceFile *device_file, - struct gbm_surface *gbm_surface, - gboolean use_modifiers, - GError **error) -{ - MetaDrmBufferGbm *buffer_gbm; - - buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM, - "device-file", device_file, - NULL); - buffer_gbm->surface = gbm_surface; - - if (!lock_front_buffer (buffer_gbm, use_modifiers, error)) - { - g_object_unref (buffer_gbm); - return NULL; - } - - return buffer_gbm; -} - -MetaDrmBufferGbm * -meta_drm_buffer_gbm_new_take (MetaDeviceFile *device_file, - struct gbm_bo *bo, - gboolean use_modifiers, - GError **error) -{ - MetaDrmBufferGbm *buffer_gbm; - - buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM, - "device-file", device_file, - NULL); - - if (!init_fb_id (buffer_gbm, bo, use_modifiers, error)) - { - g_object_unref (buffer_gbm); - return NULL; - } - - buffer_gbm->bo = bo; - - return buffer_gbm; -} - -static gboolean -meta_drm_buffer_gbm_fill_timings (MetaDrmBuffer *buffer, - CoglFrameInfo *info, - GError **error) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer); - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = - meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - CoglDisplay *cogl_display = cogl_context->display; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - EGLDisplay egl_display = cogl_renderer_egl->edpy; - EGLImageKHR egl_image; - CoglPixelFormat cogl_format; - CoglEglImageFlags flags; - g_autoptr (CoglOffscreen) cogl_fbo = NULL; - CoglTexture2D *cogl_tex; - uint32_t n_planes; - uint64_t *modifiers; - uint32_t *strides; - uint32_t *offsets; - uint32_t width; - uint32_t height; - uint32_t drm_format; - int *fds; - gboolean result; - int dmabuf_fd = -1; - uint32_t i; - - dmabuf_fd = gbm_bo_get_fd (buffer_gbm->bo); - if (dmabuf_fd == -1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to export buffer's DMA fd: %s", - g_strerror (errno)); - return FALSE; - } - - drm_format = gbm_bo_get_format (buffer_gbm->bo); - result = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); - g_assert (result); - - width = gbm_bo_get_width (buffer_gbm->bo); - height = gbm_bo_get_height (buffer_gbm->bo); - n_planes = gbm_bo_get_plane_count (buffer_gbm->bo); - fds = g_alloca (sizeof (int) * n_planes); - strides = g_alloca (sizeof (uint32_t) * n_planes); - offsets = g_alloca (sizeof (uint32_t) * n_planes); - modifiers = g_alloca (sizeof (uint64_t) * n_planes); - - for (i = 0; i < n_planes; i++) - { - fds[i] = dmabuf_fd; - strides[i] = gbm_bo_get_stride_for_plane (buffer_gbm->bo, i); - offsets[i] = gbm_bo_get_offset (buffer_gbm->bo, i); - modifiers[i] = gbm_bo_get_modifier (buffer_gbm->bo); - } - - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - width, - height, - drm_format, - n_planes, - fds, - strides, - offsets, - modifiers, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - goto out; - - flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; - cogl_tex = cogl_egl_texture_2d_new_from_image (cogl_context, - width, - height, - cogl_format, - egl_image, - flags, - error); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - if (!cogl_tex) - goto out; - - cogl_fbo = cogl_offscreen_new_with_texture (COGL_TEXTURE (cogl_tex)); - cogl_object_unref (cogl_tex); - - if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_GET_GPU_TIME)) - { - info->gpu_time_before_buffer_swap_ns = - cogl_context_get_gpu_time_ns (cogl_context); - } - - info->cpu_time_before_buffer_swap_us = g_get_monotonic_time (); - - /* Set up a timestamp query for when all rendering will be finished. */ - if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_TIMESTAMP_QUERY)) - { - info->timestamp_query = - cogl_framebuffer_create_timestamp_query (COGL_FRAMEBUFFER (cogl_fbo)); - } - -out: - close (dmabuf_fd); - - return TRUE; -} - -static gboolean -meta_drm_buffer_gbm_blit_to_framebuffer (CoglScanout *scanout, - CoglFramebuffer *framebuffer, - int x, - int y, - GError **error) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (scanout); - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = - meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - CoglDisplay *cogl_display = cogl_context->display; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - EGLDisplay egl_display = cogl_renderer_egl->edpy; - EGLImageKHR egl_image; - CoglPixelFormat cogl_format; - CoglEglImageFlags flags; - CoglOffscreen *cogl_fbo = NULL; - CoglTexture2D *cogl_tex; - uint32_t n_planes; - uint64_t *modifiers; - uint32_t *strides; - uint32_t *offsets; - uint32_t width; - uint32_t height; - uint32_t drm_format; - int *fds; - gboolean result; - int dmabuf_fd = -1; - uint32_t i; - - dmabuf_fd = gbm_bo_get_fd (buffer_gbm->bo); - if (dmabuf_fd == -1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS, - "Failed to export buffer's DMA fd: %s", - g_strerror (errno)); - return FALSE; - } - - drm_format = gbm_bo_get_format (buffer_gbm->bo); - result = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); - g_assert (result); - - width = gbm_bo_get_width (buffer_gbm->bo); - height = gbm_bo_get_height (buffer_gbm->bo); - n_planes = gbm_bo_get_plane_count (buffer_gbm->bo); - fds = g_alloca (sizeof (int) * n_planes); - strides = g_alloca (sizeof (uint32_t) * n_planes); - offsets = g_alloca (sizeof (uint32_t) * n_planes); - modifiers = g_alloca (sizeof (uint64_t) * n_planes); - - for (i = 0; i < n_planes; i++) - { - fds[i] = dmabuf_fd; - strides[i] = gbm_bo_get_stride_for_plane (buffer_gbm->bo, i); - offsets[i] = gbm_bo_get_offset (buffer_gbm->bo, i); - modifiers[i] = gbm_bo_get_modifier (buffer_gbm->bo); - } - - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - width, - height, - drm_format, - n_planes, - fds, - strides, - offsets, - modifiers, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - { - result = FALSE; - goto out; - } - - flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; - cogl_tex = cogl_egl_texture_2d_new_from_image (cogl_context, - width, - height, - cogl_format, - egl_image, - flags, - error); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - if (!cogl_tex) - { - result = FALSE; - goto out; - } - - cogl_fbo = cogl_offscreen_new_with_texture (COGL_TEXTURE (cogl_tex)); - cogl_object_unref (cogl_tex); - - if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (cogl_fbo), error)) - { - result = FALSE; - goto out; - } - - result = cogl_blit_framebuffer (COGL_FRAMEBUFFER (cogl_fbo), - framebuffer, - 0, 0, - x, y, - width, height, - error); - -out: - g_clear_object (&cogl_fbo); - close (dmabuf_fd); - - return result; -} - -static void -cogl_scanout_iface_init (CoglScanoutInterface *iface) -{ - iface->blit_to_framebuffer = meta_drm_buffer_gbm_blit_to_framebuffer; -} - -static void -meta_drm_buffer_gbm_finalize (GObject *object) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (object); - - if (buffer_gbm->bo) - { - if (buffer_gbm->surface) - gbm_surface_release_buffer (buffer_gbm->surface, buffer_gbm->bo); - else - gbm_bo_destroy (buffer_gbm->bo); - } - - G_OBJECT_CLASS (meta_drm_buffer_gbm_parent_class)->finalize (object); -} - -static void -meta_drm_buffer_gbm_init (MetaDrmBufferGbm *buffer_gbm) -{ -} - -static void -meta_drm_buffer_gbm_class_init (MetaDrmBufferGbmClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaDrmBufferClass *buffer_class = META_DRM_BUFFER_CLASS (klass); - - object_class->finalize = meta_drm_buffer_gbm_finalize; - - buffer_class->get_width = meta_drm_buffer_gbm_get_width; - buffer_class->get_height = meta_drm_buffer_gbm_get_height; - buffer_class->get_stride = meta_drm_buffer_gbm_get_stride; - buffer_class->get_format = meta_drm_buffer_gbm_get_format; - buffer_class->fill_timings = meta_drm_buffer_gbm_fill_timings; -} diff --git a/src/backends/native/meta-drm-buffer-gbm.h b/src/backends/native/meta-drm-buffer-gbm.h deleted file mode 100644 index 0413c9fa2..000000000 --- a/src/backends/native/meta-drm-buffer-gbm.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2018 Canonical Ltd. - * Copyright (C) 2019 Red Hat Inc. - * - * 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. - * - */ - -#ifndef META_DRM_BUFFER_GBM_H -#define META_DRM_BUFFER_GBM_H - -#include <gbm.h> - -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-drm-buffer-private.h" - -#define META_TYPE_DRM_BUFFER_GBM (meta_drm_buffer_gbm_get_type ()) -G_DECLARE_FINAL_TYPE (MetaDrmBufferGbm, - meta_drm_buffer_gbm, - META, DRM_BUFFER_GBM, - MetaDrmBuffer) - -MetaDrmBufferGbm * meta_drm_buffer_gbm_new_lock_front (MetaDeviceFile *device_file, - struct gbm_surface *gbm_surface, - gboolean use_modifiers, - GError **error); - - -MetaDrmBufferGbm * meta_drm_buffer_gbm_new_take (MetaDeviceFile *device_file, - struct gbm_bo *gbm_bo, - gboolean use_modifiers, - GError **error); - -struct gbm_bo * meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm); - -#endif /* META_DRM_BUFFER_GBM_H */ diff --git a/src/backends/native/meta-drm-buffer-import.c b/src/backends/native/meta-drm-buffer-import.c deleted file mode 100644 index 77cd138d2..000000000 --- a/src/backends/native/meta-drm-buffer-import.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016,2017 Red Hat - * Copyright (C) 2018,2019 DisplayLink (UK) Ltd. - * Copyright (C) 2018 Canonical Ltd. - * - * 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. - * - */ - -#include "config.h" - -#include "backends/native/meta-drm-buffer-import.h" - -#include <drm_fourcc.h> -#include <errno.h> -#include <fcntl.h> -#include <xf86drm.h> - -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-renderer-native.h" - -struct _MetaDrmBufferImport -{ - MetaDrmBuffer parent; - - MetaDrmBufferGbm *importee; -}; - -G_DEFINE_TYPE (MetaDrmBufferImport, meta_drm_buffer_import, - META_TYPE_DRM_BUFFER) - -static int -meta_drm_buffer_import_get_width (MetaDrmBuffer *buffer) -{ - MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer); - - return meta_drm_buffer_get_width (META_DRM_BUFFER (buffer_import->importee)); -} - -static int -meta_drm_buffer_import_get_height (MetaDrmBuffer *buffer) -{ - MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer); - - return meta_drm_buffer_get_height (META_DRM_BUFFER (buffer_import->importee)); -} - -static int -meta_drm_buffer_import_get_stride (MetaDrmBuffer *buffer) -{ - MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer); - - return meta_drm_buffer_get_stride (META_DRM_BUFFER (buffer_import->importee)); -} - -static uint32_t -meta_drm_buffer_import_get_format (MetaDrmBuffer *buffer) -{ - MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer); - - return meta_drm_buffer_get_format (META_DRM_BUFFER (buffer_import->importee)); -} - -static struct gbm_bo * -dmabuf_to_gbm_bo (struct gbm_device *importer, - int dmabuf_fd, - uint32_t width, - uint32_t height, - uint32_t stride, - uint32_t format) -{ - struct gbm_import_fd_data data = { - .fd = dmabuf_fd, - .width = width, - .height = height, - .stride = stride, - .format = format - }; - - return gbm_bo_import (importer, - GBM_BO_IMPORT_FD, - &data, - GBM_BO_USE_SCANOUT); -} - -static gboolean -import_gbm_buffer (MetaDrmBufferImport *buffer_import, - struct gbm_device *importer, - GError **error) -{ - MetaDrmFbArgs fb_args = { 0, }; - struct gbm_bo *primary_bo; - struct gbm_bo *imported_bo; - int dmabuf_fd; - gboolean ret; - - primary_bo = meta_drm_buffer_gbm_get_bo (buffer_import->importee); - - dmabuf_fd = gbm_bo_get_fd (primary_bo); - if (dmabuf_fd == -1) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "getting dmabuf fd failed"); - return FALSE; - } - - fb_args.strides[0] = gbm_bo_get_stride (primary_bo); - fb_args.width = gbm_bo_get_width (primary_bo); - fb_args.height = gbm_bo_get_height (primary_bo); - fb_args.format = gbm_bo_get_format (primary_bo); - - imported_bo = dmabuf_to_gbm_bo (importer, - dmabuf_fd, - fb_args.width, - fb_args.height, - fb_args.strides[0], - fb_args.format); - if (!imported_bo) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "importing dmabuf fd failed"); - ret = FALSE; - goto out_close; - } - - fb_args.handles[0] = gbm_bo_get_handle (imported_bo).u32; - - ret = meta_drm_buffer_ensure_fb_id (META_DRM_BUFFER (buffer_import), - FALSE /* use_modifiers */, - &fb_args, - error); - - gbm_bo_destroy (imported_bo); - -out_close: - close (dmabuf_fd); - - return ret; -} - -MetaDrmBufferImport * -meta_drm_buffer_import_new (MetaDeviceFile *device_file, - struct gbm_device *gbm_device, - MetaDrmBufferGbm *buffer_gbm, - GError **error) -{ - MetaDrmBufferImport *buffer_import; - - buffer_import = g_object_new (META_TYPE_DRM_BUFFER_IMPORT, - "device-file", device_file, - NULL); - g_set_object (&buffer_import->importee, buffer_gbm); - - if (!import_gbm_buffer (buffer_import, gbm_device, error)) - { - g_object_unref (buffer_import); - return NULL; - } - - return buffer_import; -} - -static void -meta_drm_buffer_import_finalize (GObject *object) -{ - MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (object); - - g_clear_object (&buffer_import->importee); - - G_OBJECT_CLASS (meta_drm_buffer_import_parent_class)->finalize (object); -} - -static void -meta_drm_buffer_import_init (MetaDrmBufferImport *buffer_import) -{ -} - -static void -meta_drm_buffer_import_class_init (MetaDrmBufferImportClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaDrmBufferClass *buffer_class = META_DRM_BUFFER_CLASS (klass); - - object_class->finalize = meta_drm_buffer_import_finalize; - - buffer_class->get_width = meta_drm_buffer_import_get_width; - buffer_class->get_height = meta_drm_buffer_import_get_height; - buffer_class->get_stride = meta_drm_buffer_import_get_stride; - buffer_class->get_format = meta_drm_buffer_import_get_format; -} diff --git a/src/backends/native/meta-drm-buffer-import.h b/src/backends/native/meta-drm-buffer-import.h deleted file mode 100644 index faff560fa..000000000 --- a/src/backends/native/meta-drm-buffer-import.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2018 Canonical Ltd. - * Copyright (C) 2019 Red Hat Inc. - * Copyright (C) 2019 DisplayLink (UK) Ltd. - * - * 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. - * - */ - -#ifndef META_DRM_BUFFER_IMPORT_H -#define META_DRM_BUFFER_IMPORT_H - -#include <gbm.h> - -#include "backends/native/meta-drm-buffer.h" -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-gpu-kms.h" - -#define META_TYPE_DRM_BUFFER_IMPORT (meta_drm_buffer_import_get_type ()) -G_DECLARE_FINAL_TYPE (MetaDrmBufferImport, - meta_drm_buffer_import, - META, DRM_BUFFER_IMPORT, - MetaDrmBuffer) - -/* - * MetaDrmBufferImport is a buffer that refers to the storage of a - * MetaDrmBufferGbm buffer on another MetaGpuKms. - * - * When creating an imported buffer, the given GBM buffer is exported - * as a dma_buf and then imported to the given MetaGpuKms. A reference - * is kept to the GBM buffer so that it won't disappear while the - * imported buffer exists. - * - * The import has a high chance of failing under normal operating - * conditions and needs to be handled with fallbacks to something else. - */ -MetaDrmBufferImport * meta_drm_buffer_import_new (MetaDeviceFile *device_file, - struct gbm_device *gbm_device, - MetaDrmBufferGbm *buffer_gbm, - GError **error); - -#endif /* META_DRM_BUFFER_IMPORT_H */ diff --git a/src/backends/native/meta-drm-buffer-private.h b/src/backends/native/meta-drm-buffer-private.h deleted file mode 100644 index a54ce7c31..000000000 --- a/src/backends/native/meta-drm-buffer-private.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2018 Canonical Ltd. - * Copyright (C) 2019-2020 Red Hat Inc. - * - * 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. - */ - -#ifndef META_DRM_BUFFER_PRIVATE_H -#define META_DRM_BUFFER_PRIVATE_H - -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-drm-buffer.h" - -typedef struct _MetaDrmFbArgs -{ - uint32_t width; - uint32_t height; - uint32_t format; - uint32_t handles[4]; - uint32_t offsets[4]; - uint32_t strides[4]; - uint64_t modifiers[4]; -} MetaDrmFbArgs; - -struct _MetaDrmBufferClass -{ - GObjectClass parent_class; - - int (* get_width) (MetaDrmBuffer *buffer); - int (* get_height) (MetaDrmBuffer *buffer); - int (* get_stride) (MetaDrmBuffer *buffer); - uint32_t (* get_format) (MetaDrmBuffer *buffer); - - gboolean (* fill_timings) (MetaDrmBuffer *buffer, - CoglFrameInfo *info, - GError **error); -}; - -MetaDeviceFile * meta_drm_buffer_get_device_file (MetaDrmBuffer *buffer); - -gboolean meta_drm_buffer_ensure_fb_id (MetaDrmBuffer *buffer, - gboolean use_modifiers, - const MetaDrmFbArgs *fb_args, - GError **error); - -gboolean meta_drm_buffer_ensure_fb_in_impl (MetaDrmBuffer *buffer, - gboolean use_modifiers, - const MetaDrmFbArgs *fb_args, - GError **error); - -#endif /* META_DRM_BUFFER_PRIVATE_H */ diff --git a/src/backends/native/meta-drm-buffer.c b/src/backends/native/meta-drm-buffer.c deleted file mode 100644 index 1da622037..000000000 --- a/src/backends/native/meta-drm-buffer.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016-2020 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * Copyright (C) 2018 Canonical Ltd. - * - * 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. - * - * Author: Daniel van Vugt <daniel.van.vugt@canonical.com> - */ - -#include "config.h" - -#include "backends/native/meta-drm-buffer-private.h" - -#include <drm_fourcc.h> - -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-kms-utils.h" - -#define INVALID_FB_ID 0U - -enum -{ - PROP_0, - - PROP_DEVICE_FILE, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef struct _MetaDrmBufferPrivate -{ - MetaDeviceFile *device_file; - uint32_t fb_id; -} MetaDrmBufferPrivate; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaDrmBuffer, meta_drm_buffer, - G_TYPE_OBJECT) - -MetaDeviceFile * -meta_drm_buffer_get_device_file (MetaDrmBuffer *buffer) -{ - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - return priv->device_file; -} - -gboolean -meta_drm_buffer_ensure_fb_id (MetaDrmBuffer *buffer, - gboolean use_modifiers, - const MetaDrmFbArgs *fb_args, - GError **error) -{ - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - int fd; - MetaDrmFormatBuf tmp; - uint32_t fb_id; - - fd = meta_device_file_get_fd (priv->device_file); - - if (use_modifiers && fb_args->modifiers[0] != DRM_FORMAT_MOD_INVALID) - { - if (drmModeAddFB2WithModifiers (fd, - fb_args->width, - fb_args->height, - fb_args->format, - fb_args->handles, - fb_args->strides, - fb_args->offsets, - fb_args->modifiers, - &fb_id, - DRM_MODE_FB_MODIFIERS)) - { - g_set_error (error, - G_IO_ERROR, - g_io_error_from_errno (errno), - "drmModeAddFB2WithModifiers failed: %s", - g_strerror (errno)); - return FALSE; - } - } - else if (drmModeAddFB2 (fd, - fb_args->width, - fb_args->height, - fb_args->format, - fb_args->handles, - fb_args->strides, - fb_args->offsets, - &fb_id, - 0)) - { - if (fb_args->format != DRM_FORMAT_XRGB8888) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "drmModeAddFB does not support format '%s' (0x%x)", - meta_drm_format_to_string (&tmp, fb_args->format), - fb_args->format); - return FALSE; - } - - if (drmModeAddFB (fd, - fb_args->width, - fb_args->height, - 24, - 32, - fb_args->strides[0], - fb_args->handles[0], - &fb_id)) - { - g_set_error (error, - G_IO_ERROR, - g_io_error_from_errno (errno), - "drmModeAddFB failed: %s", - g_strerror (errno)); - return FALSE; - } - } - - priv->fb_id = fb_id; - return TRUE; -} - -static void -meta_drm_buffer_release_fb_id (MetaDrmBuffer *buffer) -{ - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - int fd; - int ret; - - fd = meta_device_file_get_fd (priv->device_file); - ret = drmModeRmFB (fd, priv->fb_id); - if (ret != 0) - g_warning ("drmModeRmFB: %s", g_strerror (-ret)); - - priv->fb_id = 0; -} - -uint32_t -meta_drm_buffer_get_fb_id (MetaDrmBuffer *buffer) -{ - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - return priv->fb_id; -} - -int -meta_drm_buffer_get_width (MetaDrmBuffer *buffer) -{ - return META_DRM_BUFFER_GET_CLASS (buffer)->get_width (buffer); -} - -int -meta_drm_buffer_get_height (MetaDrmBuffer *buffer) -{ - return META_DRM_BUFFER_GET_CLASS (buffer)->get_height (buffer); -} - -int -meta_drm_buffer_get_stride (MetaDrmBuffer *buffer) -{ - return META_DRM_BUFFER_GET_CLASS (buffer)->get_stride (buffer); -} - -uint32_t -meta_drm_buffer_get_format (MetaDrmBuffer *buffer) -{ - return META_DRM_BUFFER_GET_CLASS (buffer)->get_format (buffer); -} - -gboolean -meta_drm_buffer_supports_fill_timings (MetaDrmBuffer *buffer) -{ - return META_DRM_BUFFER_GET_CLASS (buffer)->fill_timings != NULL; -} - -gboolean -meta_drm_buffer_fill_timings (MetaDrmBuffer *buffer, - CoglFrameInfo *info, - GError **error) -{ - if (!meta_drm_buffer_supports_fill_timings (buffer)) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Buffer doesn't support filling timing info"); - return FALSE; - } - - return META_DRM_BUFFER_GET_CLASS (buffer)->fill_timings (buffer, info, error); -} - -static void -meta_drm_buffer_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (object); - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - switch (prop_id) - { - case PROP_DEVICE_FILE: - g_value_set_pointer (value, priv->device_file); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_drm_buffer_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (object); - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - switch (prop_id) - { - case PROP_DEVICE_FILE: - priv->device_file = g_value_get_pointer (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_drm_buffer_finalize (GObject *object) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (object); - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - if (priv->fb_id != INVALID_FB_ID) - meta_drm_buffer_release_fb_id (buffer); - meta_device_file_release (priv->device_file); - - G_OBJECT_CLASS (meta_drm_buffer_parent_class)->finalize (object); -} - -static void -meta_drm_buffer_constructed (GObject *object) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (object); - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - meta_device_file_acquire (priv->device_file); - - G_OBJECT_CLASS (meta_drm_buffer_parent_class)->constructed (object); -} - -static void -meta_drm_buffer_init (MetaDrmBuffer *buffer) -{ -} - -static void -meta_drm_buffer_class_init (MetaDrmBufferClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_drm_buffer_get_property; - object_class->set_property = meta_drm_buffer_set_property; - object_class->constructed = meta_drm_buffer_constructed; - object_class->finalize = meta_drm_buffer_finalize; - - obj_props[PROP_DEVICE_FILE] = - g_param_spec_pointer ("device-file", - "device file", - "MetaDeviceFile", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/native/meta-drm-buffer.h b/src/backends/native/meta-drm-buffer.h deleted file mode 100644 index d32135591..000000000 --- a/src/backends/native/meta-drm-buffer.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2018 Canonical Ltd. - * Copyright (C) 2019-2020 Red Hat Inc. - * - * 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. - * - * Author: Daniel van Vugt <daniel.van.vugt@canonical.com> - */ - -#ifndef META_DRM_BUFFER_H -#define META_DRM_BUFFER_H - -#include <glib-object.h> -#include <stdint.h> - -#include "cogl/cogl.h" - -#define META_TYPE_DRM_BUFFER (meta_drm_buffer_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaDrmBuffer, - meta_drm_buffer, - META, DRM_BUFFER, - GObject) - -uint32_t meta_drm_buffer_get_fb_id (MetaDrmBuffer *buffer); - -int meta_drm_buffer_get_width (MetaDrmBuffer *buffer); - -int meta_drm_buffer_get_height (MetaDrmBuffer *buffer); - -int meta_drm_buffer_get_stride (MetaDrmBuffer *buffer); - -uint32_t meta_drm_buffer_get_format (MetaDrmBuffer *buffer); - -gboolean meta_drm_buffer_supports_fill_timings (MetaDrmBuffer *buffer); - -gboolean meta_drm_buffer_fill_timings (MetaDrmBuffer *buffer, - CoglFrameInfo *info, - GError **error); - -#endif /* META_DRM_BUFFER_H */ diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c deleted file mode 100644 index 97b47f9f9..000000000 --- a/src/backends/native/meta-gpu-kms.c +++ /dev/null @@ -1,422 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. - * - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-gpu-kms.h" - -#include <drm.h> -#include <drm_fourcc.h> -#include <errno.h> -#include <poll.h> -#include <string.h> -#include <time.h> -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "backends/meta-crtc.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-output.h" -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-crtc-mode-kms.h" -#include "backends/native/meta-kms-connector.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-mode.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-launcher.h" -#include "backends/native/meta-output-kms.h" - -struct _MetaGpuKms -{ - MetaGpu parent; - - MetaKmsDevice *kms_device; - - uint32_t id; - int fd; - - gboolean resources_init_failed_before; -}; - -G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU) - -gboolean -meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms, - MetaCrtc *crtc) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *l; - gboolean connected_crtc_found; - - g_assert (meta_crtc_get_gpu (crtc) == META_GPU (gpu_kms)); - - if (meta_monitor_manager_get_power_save_mode (monitor_manager)) - return FALSE; - - connected_crtc_found = FALSE; - for (l = meta_gpu_get_outputs (gpu); l; l = l->next) - { - MetaOutput *output = l->data; - MetaCrtc *assigned_crtc; - - assigned_crtc = meta_output_get_assigned_crtc (output); - if (assigned_crtc == crtc) - { - connected_crtc_found = TRUE; - break; - } - } - - if (!connected_crtc_found) - return FALSE; - - return TRUE; -} - -MetaKmsDevice * -meta_gpu_kms_get_kms_device (MetaGpuKms *gpu_kms) -{ - return gpu_kms->kms_device; -} - -uint32_t -meta_gpu_kms_get_id (MetaGpuKms *gpu_kms) -{ - return gpu_kms->id; -} - -const char * -meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms) -{ - return meta_kms_device_get_path (gpu_kms->kms_device); -} - -gboolean -meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms) -{ - MetaKmsDeviceFlag flags; - - flags = meta_kms_device_get_flags (gpu_kms->kms_device); - return !!(flags & META_KMS_DEVICE_FLAG_BOOT_VGA); -} - -gboolean -meta_gpu_kms_is_platform_device (MetaGpuKms *gpu_kms) -{ - MetaKmsDeviceFlag flags; - - flags = meta_kms_device_get_flags (gpu_kms->kms_device); - return !!(flags & META_KMS_DEVICE_FLAG_PLATFORM_DEVICE); -} - -gboolean -meta_gpu_kms_disable_modifiers (MetaGpuKms *gpu_kms) -{ - MetaKmsDeviceFlag flags; - - flags = meta_kms_device_get_flags (gpu_kms->kms_device); - return !!(flags & META_KMS_DEVICE_FLAG_DISABLE_MODIFIERS); -} - -static int -compare_outputs (gconstpointer one, - gconstpointer two) -{ - MetaOutput *o_one = (MetaOutput *) one; - MetaOutput *o_two = (MetaOutput *) two; - const MetaOutputInfo *output_info_one = meta_output_get_info (o_one); - const MetaOutputInfo *output_info_two = meta_output_get_info (o_two); - - return strcmp (output_info_one->name, output_info_two->name); -} - -MetaCrtcMode * -meta_gpu_kms_get_mode_from_kms_mode (MetaGpuKms *gpu_kms, - MetaKmsMode *kms_mode) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - GList *l; - - for (l = meta_gpu_get_modes (gpu); l; l = l->next) - { - MetaCrtcModeKms *crtc_mode_kms = l->data; - - if (meta_kms_mode_equal (kms_mode, - meta_crtc_mode_kms_get_kms_mode (crtc_mode_kms))) - return META_CRTC_MODE (crtc_mode_kms); - } - - g_assert_not_reached (); - return NULL; -} - -static MetaOutput * -find_output_by_connector_id (GList *outputs, - uint32_t connector_id) -{ - GList *l; - - for (l = outputs; l; l = l->next) - { - MetaOutput *output = l->data; - - if (meta_output_kms_get_connector_id (META_OUTPUT_KMS (output)) == - connector_id) - return output; - } - - return NULL; -} - -static void -setup_output_clones (MetaGpu *gpu) -{ - GList *l; - - for (l = meta_gpu_get_outputs (gpu); l; l = l->next) - { - MetaOutput *output = l->data; - GList *k; - - for (k = meta_gpu_get_outputs (gpu); k; k = k->next) - { - MetaOutput *other_output = k->data; - - if (other_output == output) - continue; - - if (meta_output_kms_can_clone (META_OUTPUT_KMS (output), - META_OUTPUT_KMS (other_output))) - meta_output_add_possible_clone (output, other_output); - } - } -} - -static void -init_modes (MetaGpuKms *gpu_kms) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - MetaKmsDevice *kms_device = gpu_kms->kms_device; - GHashTable *modes_table; - GList *l; - GList *modes; - GHashTableIter iter; - gpointer value; - uint64_t mode_id; - - /* - * Gather all modes on all connected connectors. - */ - modes_table = g_hash_table_new ((GHashFunc) meta_kms_mode_hash, - (GEqualFunc) meta_kms_mode_equal); - for (l = meta_kms_device_get_connectors (kms_device); l; l = l->next) - { - MetaKmsConnector *kms_connector = l->data; - const MetaKmsConnectorState *state; - GList *l_mode; - - state = meta_kms_connector_get_current_state (kms_connector); - if (!state) - continue; - - for (l_mode = state->modes; l_mode; l_mode = l_mode->next) - { - MetaKmsMode *kms_mode = l_mode->data; - - g_hash_table_add (modes_table, kms_mode); - } - } - - for (l = meta_kms_device_get_fallback_modes (kms_device); l; l = l->next) - { - MetaKmsMode *fallback_mode = l->data; - - g_hash_table_add (modes_table, fallback_mode); - } - - modes = NULL; - - g_hash_table_iter_init (&iter, modes_table); - mode_id = 0; - while (g_hash_table_iter_next (&iter, NULL, &value)) - { - MetaKmsMode *kms_mode = value; - MetaCrtcModeKms *mode; - - mode = meta_crtc_mode_kms_new (kms_mode, mode_id); - modes = g_list_append (modes, mode); - - mode_id++; - } - - g_hash_table_destroy (modes_table); - - meta_gpu_take_modes (gpu, modes); -} - -static void -init_crtcs (MetaGpuKms *gpu_kms) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - MetaKmsDevice *kms_device = gpu_kms->kms_device; - GList *l; - GList *crtcs; - - crtcs = NULL; - - for (l = meta_kms_device_get_crtcs (kms_device); l; l = l->next) - { - MetaKmsCrtc *kms_crtc = l->data; - MetaCrtcKms *crtc_kms; - - crtc_kms = meta_crtc_kms_new (gpu_kms, kms_crtc); - - crtcs = g_list_append (crtcs, crtc_kms); - } - - meta_gpu_take_crtcs (gpu, crtcs); -} - -static void -init_outputs (MetaGpuKms *gpu_kms) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - GList *old_outputs; - GList *outputs; - GList *l; - - old_outputs = meta_gpu_get_outputs (gpu); - - outputs = NULL; - - for (l = meta_kms_device_get_connectors (gpu_kms->kms_device); l; l = l->next) - { - MetaKmsConnector *kms_connector = l->data; - const MetaKmsConnectorState *connector_state; - MetaOutputKms *output_kms; - MetaOutput *old_output; - GError *error = NULL; - - connector_state = meta_kms_connector_get_current_state (kms_connector); - if (!connector_state || connector_state->non_desktop) - continue; - - old_output = - find_output_by_connector_id (old_outputs, - meta_kms_connector_get_id (kms_connector)); - output_kms = meta_output_kms_new (gpu_kms, - kms_connector, - old_output, - &error); - if (!output_kms) - { - g_warning ("Failed to create KMS output: %s", error->message); - g_error_free (error); - } - else - { - outputs = g_list_prepend (outputs, output_kms); - } - } - - - /* Sort the outputs for easier handling in MetaMonitorConfig */ - outputs = g_list_sort (outputs, compare_outputs); - meta_gpu_take_outputs (gpu, outputs); - - setup_output_clones (gpu); -} - -static gboolean -meta_gpu_kms_read_current (MetaGpu *gpu, - GError **error) -{ - MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); - - /* Note: we must not free the public structures (output, crtc, monitor - mode and monitor info) here, they must be kept alive until the API - users are done with them after we emit monitors-changed, and thus - are freed by the platform-independent layer. */ - - init_modes (gpu_kms); - init_crtcs (gpu_kms); - init_outputs (gpu_kms); - - return TRUE; -} - -gboolean -meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms) -{ - GList *l; - int n_connected_connectors = 0; - - for (l = meta_kms_device_get_connectors (gpu_kms->kms_device); l; l = l->next) - { - MetaKmsConnector *kms_connector = l->data; - - if (meta_kms_connector_get_current_state (kms_connector)) - n_connected_connectors++; - } - - return n_connected_connectors > 0; -} - -MetaGpuKms * -meta_gpu_kms_new (MetaBackendNative *backend_native, - MetaKmsDevice *kms_device, - GError **error) -{ - MetaGpuKms *gpu_kms; - - gpu_kms = g_object_new (META_TYPE_GPU_KMS, - "backend", backend_native, - NULL); - - gpu_kms->kms_device = kms_device; - - meta_gpu_kms_read_current (META_GPU (gpu_kms), NULL); - - return gpu_kms; -} - -static void -meta_gpu_kms_init (MetaGpuKms *gpu_kms) -{ - static uint32_t id = 0; - - gpu_kms->id = ++id; -} - -static void -meta_gpu_kms_class_init (MetaGpuKmsClass *klass) -{ - MetaGpuClass *gpu_class = META_GPU_CLASS (klass); - - gpu_class->read_current = meta_gpu_kms_read_current; -} diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h deleted file mode 100644 index 06f6e100a..000000000 --- a/src/backends/native/meta-gpu-kms.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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. - */ - -#ifndef META_GPU_KMS_H -#define META_GPU_KMS_H - -#include <glib-object.h> -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "backends/meta-gpu.h" -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-kms-types.h" - -#define META_TYPE_GPU_KMS (meta_gpu_kms_get_type ()) -G_DECLARE_FINAL_TYPE (MetaGpuKms, meta_gpu_kms, META, GPU_KMS, MetaGpu) - -typedef struct _MetaGpuKmsFlipClosureContainer MetaGpuKmsFlipClosureContainer; - -MetaGpuKms * meta_gpu_kms_new (MetaBackendNative *backend_native, - MetaKmsDevice *kms_device, - GError **error); - -gboolean meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms); - -gboolean meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms, - MetaCrtc *crtc); - -gboolean meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms); -gboolean meta_gpu_kms_is_platform_device (MetaGpuKms *gpu_kms); -gboolean meta_gpu_kms_disable_modifiers (MetaGpuKms *gpu_kms); - -MetaKmsDevice * meta_gpu_kms_get_kms_device (MetaGpuKms *gpu_kms); - -uint32_t meta_gpu_kms_get_id (MetaGpuKms *gpu_kms); - -const char * meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms); - -void meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms, - uint64_t state, - MetaKmsUpdate *kms_update); - -MetaCrtcMode * meta_gpu_kms_get_mode_from_kms_mode (MetaGpuKms *gpu_kms, - MetaKmsMode *kms_mode); - -gboolean meta_drm_mode_equal (const drmModeModeInfo *one, - const drmModeModeInfo *two); - -MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms, - MetaCrtc *crtc, - GClosure *flip_closure); - -void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container); - -#endif /* META_GPU_KMS_H */ diff --git a/src/backends/native/meta-input-device-native.c b/src/backends/native/meta-input-device-native.c deleted file mode 100644 index 468aef557..000000000 --- a/src/backends/native/meta-input-device-native.c +++ /dev/null @@ -1,1599 +0,0 @@ -/* - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Damien Lespiau <damien.lespiau@intel.com> - * Author: Jonas Ådahl <jadahl@gmail.com> - */ - -#include "config.h" - -#include <math.h> -#include <cairo-gobject.h> - -#include "backends/meta-backend-private.h" -#include "backends/native/meta-input-thread.h" -#include "clutter/clutter-mutter.h" - -G_DEFINE_TYPE (MetaInputDeviceNative, - meta_input_device_native, - META_TYPE_INPUT_DEVICE) - -enum -{ - PROP_0, - PROP_DEVICE_MATRIX, - PROP_OUTPUT_ASPECT_RATIO, - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS] = { 0 }; - -typedef struct _SlowKeysEventPending -{ - MetaInputDeviceNative *device; - ClutterEvent *event; - GSource *timer; -} SlowKeysEventPending; - -typedef struct _PadFeature PadFeature; - -struct _PadFeature -{ - ClutterInputDevicePadFeature feature; - int n_feature; - int group; - gboolean mode_switch; -}; - -static void clear_slow_keys (MetaInputDeviceNative *device); -static void stop_bounce_keys (MetaInputDeviceNative *device); -static void stop_toggle_slowkeys (MetaInputDeviceNative *device); -static void stop_mousekeys_move (MetaInputDeviceNative *device); - -static void -meta_input_device_native_finalize (GObject *object) -{ - MetaInputDeviceNative *device_evdev = META_INPUT_DEVICE_NATIVE (object); - - g_warn_if_fail (!device_evdev->libinput_device); - - clear_slow_keys (device_evdev); - stop_bounce_keys (device_evdev); - stop_toggle_slowkeys (device_evdev); - stop_mousekeys_move (device_evdev); - - g_clear_pointer (&device_evdev->pad_features, g_array_unref); - g_clear_pointer (&device_evdev->modes, g_array_unref); - - G_OBJECT_CLASS (meta_input_device_native_parent_class)->finalize (object); -} - -static void -meta_input_device_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaInputDeviceNative *device = META_INPUT_DEVICE_NATIVE (object); - - switch (prop_id) - { - case PROP_DEVICE_MATRIX: - { - const cairo_matrix_t *matrix = g_value_get_boxed (value); - cairo_matrix_init_identity (&device->device_matrix); - cairo_matrix_multiply (&device->device_matrix, - &device->device_matrix, matrix); - break; - } - case PROP_OUTPUT_ASPECT_RATIO: - device->output_ratio = g_value_get_double (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_input_device_native_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaInputDeviceNative *device = META_INPUT_DEVICE_NATIVE (object); - - switch (prop_id) - { - case PROP_DEVICE_MATRIX: - g_value_set_boxed (value, &device->device_matrix); - break; - case PROP_OUTPUT_ASPECT_RATIO: - g_value_set_double (value, device->output_ratio); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static gboolean -meta_input_device_native_is_mode_switch_button (ClutterInputDevice *device, - uint32_t group, - uint32_t button) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - int i; - - if (!device_native->pad_features) - return FALSE; - - for (i = 0; i < device_native->pad_features->len; i++) - { - PadFeature *pad_feature; - - pad_feature = &g_array_index (device_native->pad_features, PadFeature, i); - - if (pad_feature->feature == CLUTTER_PAD_FEATURE_BUTTON && - pad_feature->group == group && - pad_feature->n_feature == button) - return pad_feature->mode_switch; - } - - return FALSE; -} - -static int -meta_input_device_native_get_group_n_modes (ClutterInputDevice *device, - int group) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - - if (!device_native->modes || group >= device_native->modes->len) - return -1; - - return g_array_index (device_native->modes, int, group); -} - -static gboolean -meta_input_device_native_is_grouped (ClutterInputDevice *device, - ClutterInputDevice *other_device) -{ - MetaInputDeviceNative *device_native, *other_device_native; - - device_native = META_INPUT_DEVICE_NATIVE (device); - other_device_native = META_INPUT_DEVICE_NATIVE (other_device); - - return device_native->group == other_device_native->group; -} - -static int -meta_input_device_native_get_pad_feature_group (ClutterInputDevice *device, - ClutterInputDevicePadFeature feature, - int n_feature) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - int i; - - if (!device_native->pad_features) - return -1; - - for (i = 0; i < device_native->pad_features->len; i++) - { - PadFeature *pad_feature; - - pad_feature = &g_array_index (device_native->pad_features, PadFeature, i); - - if (pad_feature->feature == feature && - pad_feature->n_feature == n_feature) - return pad_feature->group; - } - - return -1; -} - -static void -meta_input_device_native_bell_notify (MetaInputDeviceNative *device) -{ - meta_seat_impl_notify_bell_in_impl (device->seat_impl); -} - -static void -meta_input_device_native_free_pending_slow_key (gpointer data) -{ - SlowKeysEventPending *slow_keys_event = data; - - clutter_event_free (slow_keys_event->event); - g_clear_pointer (&slow_keys_event->timer, g_source_destroy); - g_free (slow_keys_event); -} - -static void -clear_slow_keys (MetaInputDeviceNative *device) -{ - g_list_free_full (device->slow_keys_list, meta_input_device_native_free_pending_slow_key); - g_list_free (device->slow_keys_list); - device->slow_keys_list = NULL; -} - -static guint -get_slow_keys_delay (ClutterInputDevice *device) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - MetaKbdA11ySettings a11y_settings; - MetaInputSettings *input_settings; - - input_settings = meta_seat_impl_get_input_settings (device_native->seat_impl); - meta_input_settings_get_kbd_a11y_settings (input_settings, &a11y_settings); - /* Settings use int, we use uint, make sure we dont go negative */ - return MAX (0, a11y_settings.slowkeys_delay); -} - -static gboolean -trigger_slow_keys (gpointer data) -{ - SlowKeysEventPending *slow_keys_event = data; - MetaInputDeviceNative *device = slow_keys_event->device; - ClutterKeyEvent *key_event = (ClutterKeyEvent *) slow_keys_event->event; - - /* Alter timestamp and emit the event */ - key_event->time = us2ms (g_get_monotonic_time ()); - _clutter_event_push (slow_keys_event->event, TRUE); - - /* Then remote the pending event */ - device->slow_keys_list = g_list_remove (device->slow_keys_list, slow_keys_event); - meta_input_device_native_free_pending_slow_key (slow_keys_event); - - if (device->a11y_flags & META_A11Y_SLOW_KEYS_BEEP_ACCEPT) - meta_input_device_native_bell_notify (device); - - return G_SOURCE_REMOVE; -} - -static int -find_pending_event_by_keycode (gconstpointer a, - gconstpointer b) -{ - const SlowKeysEventPending *pa = a; - const ClutterKeyEvent *ka = (ClutterKeyEvent *) pa->event; - const ClutterKeyEvent *kb = b; - - return kb->hardware_keycode - ka->hardware_keycode; -} - -static GSource * -timeout_source_new (MetaSeatImpl *seat_impl, - guint interval, - GSourceFunc func, - gpointer user_data) -{ - GSource *source; - - source = g_timeout_source_new (interval); - g_source_set_callback (source, - func, - user_data, NULL); - g_source_attach (source, seat_impl->input_context); - g_source_unref (source); - - return source; -} - -static gboolean -start_slow_keys (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - SlowKeysEventPending *slow_keys_event; - ClutterKeyEvent *key_event = (ClutterKeyEvent *) event; - - if (key_event->flags & CLUTTER_EVENT_FLAG_REPEATED) - return TRUE; - - slow_keys_event = g_new0 (SlowKeysEventPending, 1); - slow_keys_event->device = device; - slow_keys_event->event = clutter_event_copy (event); - slow_keys_event->timer = - timeout_source_new (device->seat_impl, - get_slow_keys_delay (CLUTTER_INPUT_DEVICE (device)), - trigger_slow_keys, - slow_keys_event); - device->slow_keys_list = g_list_append (device->slow_keys_list, slow_keys_event); - - if (device->a11y_flags & META_A11Y_SLOW_KEYS_BEEP_PRESS) - meta_input_device_native_bell_notify (device); - - return TRUE; -} - -static gboolean -stop_slow_keys (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - GList *item; - - /* Check if we have a slow key event queued for this key event */ - item = g_list_find_custom (device->slow_keys_list, event, find_pending_event_by_keycode); - if (item) - { - SlowKeysEventPending *slow_keys_event = item->data; - - device->slow_keys_list = g_list_delete_link (device->slow_keys_list, item); - meta_input_device_native_free_pending_slow_key (slow_keys_event); - - if (device->a11y_flags & META_A11Y_SLOW_KEYS_BEEP_REJECT) - meta_input_device_native_bell_notify (device); - - return TRUE; - } - - /* If no key press event was pending, just emit the key release as-is */ - return FALSE; -} - -static guint -get_debounce_delay (ClutterInputDevice *device) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - MetaKbdA11ySettings a11y_settings; - MetaInputSettings *input_settings; - - input_settings = meta_seat_impl_get_input_settings (device_native->seat_impl); - meta_input_settings_get_kbd_a11y_settings (input_settings, &a11y_settings); - /* Settings use int, we use uint, make sure we dont go negative */ - return MAX (0, a11y_settings.debounce_delay); -} - -static gboolean -clear_bounce_keys (gpointer data) -{ - MetaInputDeviceNative *device = data; - - device->debounce_key = 0; - device->debounce_timer = 0; - - return G_SOURCE_REMOVE; -} - -static void -start_bounce_keys (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - stop_bounce_keys (device); - - device->debounce_key = ((ClutterKeyEvent *) event)->hardware_keycode; - device->debounce_timer = - timeout_source_new (device->seat_impl, - get_debounce_delay (CLUTTER_INPUT_DEVICE (device)), - clear_bounce_keys, - device); -} - -static void -stop_bounce_keys (MetaInputDeviceNative *device) -{ - g_clear_pointer (&device->debounce_timer, g_source_destroy); -} - -static void -notify_bounce_keys_reject (MetaInputDeviceNative *device) -{ - if (device->a11y_flags & META_A11Y_BOUNCE_KEYS_BEEP_REJECT) - meta_input_device_native_bell_notify (device); -} - -static gboolean -debounce_key (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - return (device->debounce_key == ((ClutterKeyEvent *) event)->hardware_keycode); -} - -static gboolean -key_event_is_modifier (ClutterEvent *event) -{ - switch (event->key.keyval) - { - case XKB_KEY_Shift_L: - case XKB_KEY_Shift_R: - case XKB_KEY_Control_L: - case XKB_KEY_Control_R: - case XKB_KEY_Alt_L: - case XKB_KEY_Alt_R: - case XKB_KEY_Meta_L: - case XKB_KEY_Meta_R: - case XKB_KEY_Super_L: - case XKB_KEY_Super_R: - case XKB_KEY_Hyper_L: - case XKB_KEY_Hyper_R: - case XKB_KEY_Caps_Lock: - case XKB_KEY_Shift_Lock: - return TRUE; - default: - return FALSE; - } -} - -static void -notify_stickykeys_mask (MetaInputDeviceNative *device) -{ - meta_seat_impl_notify_kbd_a11y_mods_state_changed_in_impl (device->seat_impl, - device->stickykeys_latched_mask, - device->stickykeys_locked_mask); -} - -static void -update_internal_xkb_state (MetaInputDeviceNative *device, - xkb_mod_mask_t new_latched_mask, - xkb_mod_mask_t new_locked_mask) -{ - MetaSeatImpl *seat_impl = device->seat_impl; - xkb_mod_mask_t depressed_mods; - xkb_mod_mask_t latched_mods; - xkb_mod_mask_t locked_mods; - xkb_mod_mask_t group_mods; - struct xkb_state *xkb_state; - - g_rw_lock_writer_lock (&seat_impl->state_lock); - - xkb_state = meta_seat_impl_get_xkb_state_in_impl (seat_impl); - depressed_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_DEPRESSED); - latched_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LATCHED); - locked_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LOCKED); - - latched_mods &= ~device->stickykeys_latched_mask; - locked_mods &= ~device->stickykeys_locked_mask; - - device->stickykeys_latched_mask = new_latched_mask; - device->stickykeys_locked_mask = new_locked_mask; - - latched_mods |= device->stickykeys_latched_mask; - locked_mods |= device->stickykeys_locked_mask; - - group_mods = xkb_state_serialize_layout (xkb_state, XKB_STATE_LAYOUT_EFFECTIVE); - - xkb_state_update_mask (xkb_state, - depressed_mods, - latched_mods, - locked_mods, - 0, 0, group_mods); - notify_stickykeys_mask (device); - - g_rw_lock_writer_unlock (&seat_impl->state_lock); -} - -static void -update_stickykeys_event (ClutterEvent *event, - MetaInputDeviceNative *device, - xkb_mod_mask_t new_latched_mask, - xkb_mod_mask_t new_locked_mask) -{ - MetaSeatImpl *seat_impl = device->seat_impl; - xkb_mod_mask_t effective_mods; - xkb_mod_mask_t latched_mods; - xkb_mod_mask_t locked_mods; - struct xkb_state *xkb_state; - - update_internal_xkb_state (device, new_latched_mask, new_locked_mask); - - xkb_state = meta_seat_impl_get_xkb_state_in_impl (seat_impl); - effective_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE); - latched_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LATCHED); - locked_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LOCKED); - - _clutter_event_set_state_full (event, - seat_impl->button_state, - device->stickykeys_depressed_mask, - latched_mods, - locked_mods, - effective_mods | seat_impl->button_state); -} - -static void -notify_stickykeys_change (MetaInputDeviceNative *device) -{ - /* Every time sticky keys setting is changed, clear the masks */ - device->stickykeys_depressed_mask = 0; - update_internal_xkb_state (device, 0, 0); - - meta_seat_impl_notify_kbd_a11y_flags_changed_in_impl (device->seat_impl, - device->a11y_flags, - META_A11Y_STICKY_KEYS_ENABLED); -} - -static void -set_stickykeys_off (MetaInputDeviceNative *device) -{ - device->a11y_flags &= ~META_A11Y_STICKY_KEYS_ENABLED; - notify_stickykeys_change (device); -} - -static void -set_stickykeys_on (MetaInputDeviceNative *device) -{ - device->a11y_flags |= META_A11Y_STICKY_KEYS_ENABLED; - notify_stickykeys_change (device); -} - -static void -clear_stickykeys_event (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - set_stickykeys_off (device); - update_stickykeys_event (event, device, 0, 0); -} - -static void -set_slowkeys_off (MetaInputDeviceNative *device) -{ - device->a11y_flags &= ~META_A11Y_SLOW_KEYS_ENABLED; - - meta_seat_impl_notify_kbd_a11y_flags_changed_in_impl (device->seat_impl, - device->a11y_flags, - META_A11Y_SLOW_KEYS_ENABLED); -} - -static void -set_slowkeys_on (MetaInputDeviceNative *device) -{ - device->a11y_flags |= META_A11Y_SLOW_KEYS_ENABLED; - - meta_seat_impl_notify_kbd_a11y_flags_changed_in_impl (device->seat_impl, - device->a11y_flags, - META_A11Y_SLOW_KEYS_ENABLED); -} - -static void -handle_stickykeys_press (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - MetaSeatImpl *seat_impl = device->seat_impl; - xkb_mod_mask_t depressed_mods; - xkb_mod_mask_t new_latched_mask; - xkb_mod_mask_t new_locked_mask; - struct xkb_state *xkb_state; - - if (!key_event_is_modifier (event)) - return; - - if (device->stickykeys_depressed_mask && - (device->a11y_flags & META_A11Y_STICKY_KEYS_TWO_KEY_OFF)) - { - clear_stickykeys_event (event, device); - return; - } - - xkb_state = meta_seat_impl_get_xkb_state_in_impl (seat_impl); - depressed_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_DEPRESSED); - /* Ignore the lock modifier mask, that one cannot be sticky, yet the - * CAPS_LOCK key itself counts as a modifier as it might be remapped - * to some other modifier which can be sticky. - */ - depressed_mods &= ~CLUTTER_LOCK_MASK; - - new_latched_mask = device->stickykeys_latched_mask; - new_locked_mask = device->stickykeys_locked_mask; - - device->stickykeys_depressed_mask = depressed_mods; - - if (new_locked_mask & depressed_mods) - { - new_locked_mask &= ~depressed_mods; - } - else if (new_latched_mask & depressed_mods) - { - new_locked_mask |= depressed_mods; - new_latched_mask &= ~depressed_mods; - } - else - { - new_latched_mask |= depressed_mods; - } - - update_stickykeys_event (event, device, new_latched_mask, new_locked_mask); -} - -static void -handle_stickykeys_release (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - MetaSeatImpl *seat_impl = device->seat_impl; - struct xkb_state *xkb_state; - - xkb_state = meta_seat_impl_get_xkb_state_in_impl (seat_impl); - device->stickykeys_depressed_mask = - xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_DEPRESSED); - - if (key_event_is_modifier (event)) - { - if (device->a11y_flags & META_A11Y_STICKY_KEYS_BEEP) - meta_input_device_native_bell_notify (device); - - return; - } - - if (device->stickykeys_latched_mask == 0) - return; - - update_stickykeys_event (event, device, 0, device->stickykeys_locked_mask); -} - -static gboolean -trigger_toggle_slowkeys (gpointer data) -{ - MetaInputDeviceNative *device = data; - - device->toggle_slowkeys_timer = 0; - - if (device->a11y_flags & META_A11Y_FEATURE_STATE_CHANGE_BEEP) - meta_input_device_native_bell_notify (device); - - if (device->a11y_flags & META_A11Y_SLOW_KEYS_ENABLED) - set_slowkeys_off (device); - else - set_slowkeys_on (device); - - return G_SOURCE_REMOVE; -} - -static void -start_toggle_slowkeys (MetaInputDeviceNative *device) -{ - if (device->toggle_slowkeys_timer != 0) - return; - - device->toggle_slowkeys_timer = - timeout_source_new (device->seat_impl, - 8 * 1000 /* 8 secs */, - trigger_toggle_slowkeys, - device); -} - -static void -stop_toggle_slowkeys (MetaInputDeviceNative *device) -{ - g_clear_pointer (&device->toggle_slowkeys_timer, g_source_destroy); -} - -static void -handle_enablekeys_press (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - if (event->key.keyval == XKB_KEY_Shift_L || event->key.keyval == XKB_KEY_Shift_R) - { - start_toggle_slowkeys (device); - - if (event->key.time > device->last_shift_time + 15 * 1000 /* 15 secs */) - device->shift_count = 1; - else - device->shift_count++; - - device->last_shift_time = event->key.time; - } - else - { - device->shift_count = 0; - stop_toggle_slowkeys (device); - } -} - -static void -handle_enablekeys_release (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - if (event->key.keyval == XKB_KEY_Shift_L || event->key.keyval == XKB_KEY_Shift_R) - { - stop_toggle_slowkeys (device); - if (device->shift_count >= 5) - { - device->shift_count = 0; - - if (device->a11y_flags & META_A11Y_FEATURE_STATE_CHANGE_BEEP) - meta_input_device_native_bell_notify (device); - - if (device->a11y_flags & META_A11Y_STICKY_KEYS_ENABLED) - set_stickykeys_off (device); - else - set_stickykeys_on (device); - } - } -} - -static int -get_button_index (int button) -{ - switch (button) - { - case CLUTTER_BUTTON_PRIMARY: - return 0; - case CLUTTER_BUTTON_MIDDLE: - return 1; - case CLUTTER_BUTTON_SECONDARY: - return 2; - default: - break; - } - - g_warn_if_reached (); - return 0; -} - -static void -emulate_button_press (MetaInputDeviceNative *device_evdev) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); - int btn = device_evdev->mousekeys_btn; - - if (device_evdev->mousekeys_btn_states[get_button_index (btn)]) - return; - - clutter_virtual_input_device_notify_button (device->accessibility_virtual_device, - g_get_monotonic_time (), btn, - CLUTTER_BUTTON_STATE_PRESSED); - device_evdev->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_PRESSED; -} - -static void -emulate_button_release (MetaInputDeviceNative *device_evdev) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); - int btn = device_evdev->mousekeys_btn; - - if (device_evdev->mousekeys_btn_states[get_button_index (btn)] == CLUTTER_BUTTON_STATE_RELEASED) - return; - - clutter_virtual_input_device_notify_button (device->accessibility_virtual_device, - g_get_monotonic_time (), btn, - CLUTTER_BUTTON_STATE_RELEASED); - device_evdev->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_RELEASED; -} - -static void -emulate_button_click (MetaInputDeviceNative *device) -{ - emulate_button_press (device); - emulate_button_release (device); -} - -#define MOUSEKEYS_CURVE (1.0 + (((double) 50.0) * 0.001)) - -static void -update_mousekeys_params (MetaInputDeviceNative *device, - MetaKbdA11ySettings *settings) -{ - /* Prevent us from broken settings values */ - device->mousekeys_max_speed = MAX (1, settings->mousekeys_max_speed); - device->mousekeys_accel_time = MAX (1, settings->mousekeys_accel_time); - device->mousekeys_init_delay = MAX (0, settings->mousekeys_init_delay); - - device->mousekeys_curve_factor = - (((double) device->mousekeys_max_speed) / - pow ((double) device->mousekeys_accel_time, MOUSEKEYS_CURVE)); -} - -static double -mousekeys_get_speed_factor (MetaInputDeviceNative *device, - uint64_t time_us) -{ - uint32_t time; - int64_t delta_t; - int64_t init_time; - double speed; - - time = us2ms (time_us); - - if (device->mousekeys_first_motion_time == 0) - { - /* Start acceleration _after_ the first move, so take - * mousekeys_init_delay into account for t0 - */ - device->mousekeys_first_motion_time = time + device->mousekeys_init_delay; - device->mousekeys_last_motion_time = device->mousekeys_first_motion_time; - return 1.0; - } - - init_time = time - device->mousekeys_first_motion_time; - delta_t = time - device->mousekeys_last_motion_time; - - if (delta_t < 0) - return 0.0; - - if (init_time < device->mousekeys_accel_time) - speed = (double) (device->mousekeys_curve_factor * - pow ((double) init_time, MOUSEKEYS_CURVE) * delta_t / 1000.0); - else - speed = (double) (device->mousekeys_max_speed * delta_t / 1000.0); - - device->mousekeys_last_motion_time = time; - - return speed; -} - -#undef MOUSEKEYS_CURVE - -static void -emulate_pointer_motion (MetaInputDeviceNative *device_evdev, - int dx, - int dy) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); - double dx_motion; - double dy_motion; - double speed; - int64_t time_us; - - time_us = g_get_monotonic_time (); - speed = mousekeys_get_speed_factor (device_evdev, time_us); - - if (dx < 0) - dx_motion = floor (((double) dx) * speed); - else - dx_motion = ceil (((double) dx) * speed); - - if (dy < 0) - dy_motion = floor (((double) dy) * speed); - else - dy_motion = ceil (((double) dy) * speed); - - clutter_virtual_input_device_notify_relative_motion (device->accessibility_virtual_device, - time_us, dx_motion, dy_motion); -} -static gboolean -is_numlock_active (MetaInputDeviceNative *device) -{ - MetaSeatImpl *seat_impl = device->seat_impl; - struct xkb_state *xkb_state; - - xkb_state = meta_seat_impl_get_xkb_state_in_impl (seat_impl); - - return xkb_state_mod_name_is_active (xkb_state, - "Mod2", - XKB_STATE_MODS_LOCKED); -} - -static void -enable_mousekeys (MetaInputDeviceNative *device_evdev) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); - - device_evdev->mousekeys_btn = CLUTTER_BUTTON_PRIMARY; - device_evdev->move_mousekeys_timer = 0; - device_evdev->mousekeys_first_motion_time = 0; - device_evdev->mousekeys_last_motion_time = 0; - device_evdev->last_mousekeys_key = 0; - - if (device->accessibility_virtual_device) - return; - - device->accessibility_virtual_device = - clutter_seat_create_virtual_device (clutter_input_device_get_seat (device), - CLUTTER_POINTER_DEVICE); -} - -static void -disable_mousekeys (MetaInputDeviceNative *device_evdev) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); - - stop_mousekeys_move (device_evdev); - - /* Make sure we don't leave button pressed behind... */ - if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_PRIMARY)]) - { - device_evdev->mousekeys_btn = CLUTTER_BUTTON_PRIMARY; - emulate_button_release (device_evdev); - } - - if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_MIDDLE)]) - { - device_evdev->mousekeys_btn = CLUTTER_BUTTON_MIDDLE; - emulate_button_release (device_evdev); - } - - if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_SECONDARY)]) - { - device_evdev->mousekeys_btn = CLUTTER_BUTTON_SECONDARY; - emulate_button_release (device_evdev); - } - - if (device->accessibility_virtual_device) - g_clear_object (&device->accessibility_virtual_device); -} - -static gboolean -trigger_mousekeys_move (gpointer data) -{ - MetaInputDeviceNative *device = data; - int dx = 0; - int dy = 0; - - if (device->mousekeys_first_motion_time == 0) - { - /* This is the first move, Secdule at mk_init_delay */ - device->move_mousekeys_timer = - timeout_source_new (device->seat_impl, - device->mousekeys_init_delay, - trigger_mousekeys_move, - device); - - } - else - { - /* More moves, reschedule at mk_interval */ - device->move_mousekeys_timer = - timeout_source_new (device->seat_impl, - 100, /* msec between mousekey events */ - trigger_mousekeys_move, - device); - } - - /* Pointer motion */ - switch (device->last_mousekeys_key) - { - case XKB_KEY_KP_Home: - case XKB_KEY_KP_7: - case XKB_KEY_KP_Up: - case XKB_KEY_KP_8: - case XKB_KEY_KP_Page_Up: - case XKB_KEY_KP_9: - dy = -1; - break; - case XKB_KEY_KP_End: - case XKB_KEY_KP_1: - case XKB_KEY_KP_Down: - case XKB_KEY_KP_2: - case XKB_KEY_KP_Page_Down: - case XKB_KEY_KP_3: - dy = 1; - break; - default: - break; - } - - switch (device->last_mousekeys_key) - { - case XKB_KEY_KP_Home: - case XKB_KEY_KP_7: - case XKB_KEY_KP_Left: - case XKB_KEY_KP_4: - case XKB_KEY_KP_End: - case XKB_KEY_KP_1: - dx = -1; - break; - case XKB_KEY_KP_Page_Up: - case XKB_KEY_KP_9: - case XKB_KEY_KP_Right: - case XKB_KEY_KP_6: - case XKB_KEY_KP_Page_Down: - case XKB_KEY_KP_3: - dx = 1; - break; - default: - break; - } - - if (dx != 0 || dy != 0) - emulate_pointer_motion (device, dx, dy); - - /* We reschedule each time */ - return G_SOURCE_REMOVE; -} - -static void -stop_mousekeys_move (MetaInputDeviceNative *device) -{ - device->mousekeys_first_motion_time = 0; - device->mousekeys_last_motion_time = 0; - - g_clear_pointer (&device->move_mousekeys_timer, g_source_destroy); -} - -static void -start_mousekeys_move (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - device->last_mousekeys_key = event->key.keyval; - - if (device->move_mousekeys_timer != 0) - return; - - trigger_mousekeys_move (device); -} - -static gboolean -handle_mousekeys_press (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - if (!(event->key.flags & CLUTTER_EVENT_FLAG_SYNTHETIC)) - stop_mousekeys_move (device); - - /* Do not handle mousekeys if NumLock is ON */ - if (is_numlock_active (device)) - return FALSE; - - /* Button selection */ - switch (event->key.keyval) - { - case XKB_KEY_KP_Divide: - device->mousekeys_btn = CLUTTER_BUTTON_PRIMARY; - return TRUE; - case XKB_KEY_KP_Multiply: - device->mousekeys_btn = CLUTTER_BUTTON_MIDDLE; - return TRUE; - case XKB_KEY_KP_Subtract: - device->mousekeys_btn = CLUTTER_BUTTON_SECONDARY; - return TRUE; - default: - break; - } - - /* Button events */ - switch (event->key.keyval) - { - case XKB_KEY_KP_Begin: - case XKB_KEY_KP_5: - emulate_button_click (device); - return TRUE; - case XKB_KEY_KP_Insert: - case XKB_KEY_KP_0: - emulate_button_press (device); - return TRUE; - case XKB_KEY_KP_Decimal: - case XKB_KEY_KP_Delete: - emulate_button_release (device); - return TRUE; - case XKB_KEY_KP_Add: - emulate_button_click (device); - emulate_button_click (device); - return TRUE; - default: - break; - } - - /* Pointer motion */ - switch (event->key.keyval) - { - case XKB_KEY_KP_1: - case XKB_KEY_KP_2: - case XKB_KEY_KP_3: - case XKB_KEY_KP_4: - case XKB_KEY_KP_6: - case XKB_KEY_KP_7: - case XKB_KEY_KP_8: - case XKB_KEY_KP_9: - case XKB_KEY_KP_Down: - case XKB_KEY_KP_End: - case XKB_KEY_KP_Home: - case XKB_KEY_KP_Left: - case XKB_KEY_KP_Page_Down: - case XKB_KEY_KP_Page_Up: - case XKB_KEY_KP_Right: - case XKB_KEY_KP_Up: - start_mousekeys_move (event, device); - return TRUE; - default: - break; - } - - return FALSE; -} - -static gboolean -handle_mousekeys_release (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - /* Do not handle mousekeys if NumLock is ON */ - if (is_numlock_active (device)) - return FALSE; - - switch (event->key.keyval) - { - case XKB_KEY_KP_0: - case XKB_KEY_KP_1: - case XKB_KEY_KP_2: - case XKB_KEY_KP_3: - case XKB_KEY_KP_4: - case XKB_KEY_KP_5: - case XKB_KEY_KP_6: - case XKB_KEY_KP_7: - case XKB_KEY_KP_8: - case XKB_KEY_KP_9: - case XKB_KEY_KP_Add: - case XKB_KEY_KP_Begin: - case XKB_KEY_KP_Decimal: - case XKB_KEY_KP_Delete: - case XKB_KEY_KP_Divide: - case XKB_KEY_KP_Down: - case XKB_KEY_KP_End: - case XKB_KEY_KP_Home: - case XKB_KEY_KP_Insert: - case XKB_KEY_KP_Left: - case XKB_KEY_KP_Multiply: - case XKB_KEY_KP_Page_Down: - case XKB_KEY_KP_Page_Up: - case XKB_KEY_KP_Right: - case XKB_KEY_KP_Subtract: - case XKB_KEY_KP_Up: - stop_mousekeys_move (device); - return TRUE; - default: - break; - } - - return FALSE; -} - -gboolean -meta_input_device_native_process_kbd_a11y_event_in_impl (ClutterInputDevice *device, - ClutterEvent *event) -{ - MetaInputDeviceNative *device_evdev = META_INPUT_DEVICE_NATIVE (device); - - if (device_evdev->a11y_flags & META_A11Y_KEYBOARD_ENABLED) - { - if (event->type == CLUTTER_KEY_PRESS) - handle_enablekeys_press (event, device_evdev); - else - handle_enablekeys_release (event, device_evdev); - } - - if (device_evdev->a11y_flags & META_A11Y_MOUSE_KEYS_ENABLED) - { - if (event->type == CLUTTER_KEY_PRESS && - handle_mousekeys_press (event, device_evdev)) - return TRUE; /* swallow event */ - if (event->type == CLUTTER_KEY_RELEASE && - handle_mousekeys_release (event, device_evdev)) - return TRUE; /* swallow event */ - } - - if ((device_evdev->a11y_flags & META_A11Y_BOUNCE_KEYS_ENABLED) && - (get_debounce_delay (device) != 0)) - { - if ((event->type == CLUTTER_KEY_PRESS) && debounce_key (event, device_evdev)) - { - notify_bounce_keys_reject (device_evdev); - - return TRUE; - } - else if (event->type == CLUTTER_KEY_RELEASE) - start_bounce_keys (event, device_evdev); - } - - if ((device_evdev->a11y_flags & META_A11Y_SLOW_KEYS_ENABLED) && - (get_slow_keys_delay (device) != 0)) - { - if (event->type == CLUTTER_KEY_PRESS) - return start_slow_keys (event, device_evdev); - else if (event->type == CLUTTER_KEY_RELEASE) - return stop_slow_keys (event, device_evdev); - } - - if (device_evdev->a11y_flags & META_A11Y_STICKY_KEYS_ENABLED) - { - if (event->type == CLUTTER_KEY_PRESS) - handle_stickykeys_press (event, device_evdev); - else if (event->type == CLUTTER_KEY_RELEASE) - handle_stickykeys_release (event, device_evdev); - } - - return FALSE; -} - -void -meta_input_device_native_apply_kbd_a11y_settings_in_impl (MetaInputDeviceNative *device, - MetaKbdA11ySettings *settings) -{ - MetaKeyboardA11yFlags changed_flags = (device->a11y_flags ^ settings->controls); - - if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_SLOW_KEYS_ENABLED)) - clear_slow_keys (device); - - if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_BOUNCE_KEYS_ENABLED)) - device->debounce_key = 0; - - if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_STICKY_KEYS_ENABLED)) - { - device->stickykeys_depressed_mask = 0; - update_internal_xkb_state (device, 0, 0); - } - - if (changed_flags & META_A11Y_KEYBOARD_ENABLED) - { - device->toggle_slowkeys_timer = 0; - device->shift_count = 0; - device->last_shift_time = 0; - } - - if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_MOUSE_KEYS_ENABLED)) - { - if (settings->controls & - (META_A11Y_KEYBOARD_ENABLED | META_A11Y_MOUSE_KEYS_ENABLED)) - enable_mousekeys (device); - else - disable_mousekeys (device); - } - update_mousekeys_params (device, settings); - - /* Keep our own copy of keyboard a11y features flags to see what changes */ - device->a11y_flags = settings->controls; -} - -void -meta_input_device_native_a11y_maybe_notify_toggle_keys_in_impl (MetaInputDeviceNative *device) -{ - if (device->a11y_flags & META_A11Y_TOGGLE_KEYS_ENABLED) - meta_input_device_native_bell_notify (device); -} - -static void -meta_input_device_native_class_init (MetaInputDeviceNativeClass *klass) -{ - ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_input_device_native_finalize; - object_class->set_property = meta_input_device_native_set_property; - object_class->get_property = meta_input_device_native_get_property; - - device_class->is_mode_switch_button = meta_input_device_native_is_mode_switch_button; - device_class->get_group_n_modes = meta_input_device_native_get_group_n_modes; - device_class->is_grouped = meta_input_device_native_is_grouped; - device_class->get_pad_feature_group = meta_input_device_native_get_pad_feature_group; - - obj_props[PROP_DEVICE_MATRIX] = - g_param_spec_boxed ("device-matrix", - "Device input matrix", - "Device input matrix", - CAIRO_GOBJECT_TYPE_MATRIX, - CLUTTER_PARAM_READWRITE); - obj_props[PROP_OUTPUT_ASPECT_RATIO] = - g_param_spec_double ("output-aspect-ratio", - "Output aspect ratio", - "Output aspect ratio", - 0, G_MAXDOUBLE, 0, - CLUTTER_PARAM_READWRITE); - - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} - -static void -meta_input_device_native_init (MetaInputDeviceNative *self) -{ - cairo_matrix_init_identity (&self->device_matrix); - self->device_aspect_ratio = 0; - self->output_ratio = 0; -} - -static void -update_pad_features (MetaInputDeviceNative *device_native) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_native); - struct libinput_device *libinput_device; - struct libinput_tablet_pad_mode_group *mode_group; - int n_groups, n_buttons, n_rings, n_strips, n_modes, i, j; - - libinput_device = meta_input_device_native_get_libinput_device (device); - n_rings = libinput_device_tablet_pad_get_num_rings (libinput_device); - n_strips = libinput_device_tablet_pad_get_num_strips (libinput_device); - n_groups = libinput_device_tablet_pad_get_num_mode_groups (libinput_device); - n_buttons = libinput_device_tablet_pad_get_num_buttons (libinput_device); - - device_native->pad_features = g_array_new (FALSE, FALSE, sizeof (PadFeature)); - device_native->modes = g_array_sized_new (FALSE, FALSE, sizeof (int), n_groups); - - for (i = 0; i < n_groups; i++) - { - mode_group = - libinput_device_tablet_pad_get_mode_group (libinput_device, i); - - n_modes = libinput_tablet_pad_mode_group_get_num_modes (mode_group); - g_array_append_val (device_native->modes, n_modes); - - for (j = 0; j < n_buttons; j++) - { - gboolean is_mode_switch = - libinput_tablet_pad_mode_group_button_is_toggle (mode_group, j) != 0; - PadFeature feature = { CLUTTER_PAD_FEATURE_BUTTON, j, i, is_mode_switch }; - - if (libinput_tablet_pad_mode_group_has_button (mode_group, j)) - g_array_append_val (device_native->pad_features, feature); - } - - for (j = 0; j < n_rings; j++) - { - PadFeature feature = { CLUTTER_PAD_FEATURE_RING, j, i }; - - if (libinput_tablet_pad_mode_group_has_ring (mode_group, j)) - g_array_append_val (device_native->pad_features, feature); - } - - for (j = 0; j < n_strips; j++) - { - PadFeature feature = { CLUTTER_PAD_FEATURE_STRIP, j, i }; - - if (libinput_tablet_pad_mode_group_has_strip (mode_group, j)) - g_array_append_val (device_native->pad_features, feature); - } - } -} - -/* - * meta_input_device_native_new: - * @manager: the device manager - * @seat: the seat the device will belong to - * @libinput_device: the libinput device - * - * Create a new ClutterInputDevice given a libinput device and associate - * it with the provided seat. - */ -ClutterInputDevice * -meta_input_device_native_new_in_impl (MetaSeatImpl *seat_impl, - struct libinput_device *libinput_device) -{ - MetaInputDeviceNative *device; - ClutterInputDeviceType type; - char *vendor, *product; - int n_rings = 0, n_strips = 0, n_groups = 1, n_buttons = 0; - char *node_path; - double width, height; - - type = meta_input_device_native_determine_type_in_impl (libinput_device); - vendor = g_strdup_printf ("%.4x", libinput_device_get_id_vendor (libinput_device)); - product = g_strdup_printf ("%.4x", libinput_device_get_id_product (libinput_device)); - node_path = g_strdup_printf ("/dev/input/%s", libinput_device_get_sysname (libinput_device)); - - if (libinput_device_has_capability (libinput_device, - LIBINPUT_DEVICE_CAP_TABLET_PAD)) - { - n_rings = libinput_device_tablet_pad_get_num_rings (libinput_device); - n_strips = libinput_device_tablet_pad_get_num_strips (libinput_device); - n_groups = libinput_device_tablet_pad_get_num_mode_groups (libinput_device); - n_buttons = libinput_device_tablet_pad_get_num_buttons (libinput_device); - } - - device = g_object_new (META_TYPE_INPUT_DEVICE_NATIVE, - "name", libinput_device_get_name (libinput_device), - "device-type", type, - "device-mode", CLUTTER_INPUT_MODE_PHYSICAL, - "vendor-id", vendor, - "product-id", product, - "n-rings", n_rings, - "n-strips", n_strips, - "n-mode-groups", n_groups, - "n-buttons", n_buttons, - "device-node", node_path, - "seat", seat_impl->seat_native, - NULL); - - device->seat_impl = seat_impl; - device->libinput_device = libinput_device; - - libinput_device_set_user_data (libinput_device, device); - libinput_device_ref (libinput_device); - g_free (vendor); - g_free (product); - g_free (node_path); - - if (libinput_device_has_capability (libinput_device, - LIBINPUT_DEVICE_CAP_TABLET_PAD)) - update_pad_features (device); - - if (libinput_device_get_size (libinput_device, &width, &height) == 0) - device->device_aspect_ratio = width / height; - - device->group = (intptr_t) libinput_device_get_device_group (libinput_device); - - return CLUTTER_INPUT_DEVICE (device); -} - -/* - * meta_input_device_native_new_virtual: - * @seat: the seat the device will belong to - * @type: the input device type - * - * Create a new virtual ClutterInputDevice of the given type. - */ -ClutterInputDevice * -meta_input_device_native_new_virtual (MetaSeatImpl *seat_impl, - ClutterInputDeviceType type, - ClutterInputMode mode) -{ - MetaInputDeviceNative *device; - const char *name; - - switch (type) - { - case CLUTTER_KEYBOARD_DEVICE: - name = "Virtual keyboard device for seat"; - break; - case CLUTTER_POINTER_DEVICE: - name = "Virtual pointer device for seat"; - break; - case CLUTTER_TOUCHSCREEN_DEVICE: - name = "Virtual touchscreen device for seat"; - break; - default: - name = "Virtual device for seat"; - break; - }; - - device = g_object_new (META_TYPE_INPUT_DEVICE_NATIVE, - "name", name, - "device-type", type, - "device-mode", mode, - "seat", seat_impl->seat_native, - NULL); - - device->seat_impl = seat_impl; - - return CLUTTER_INPUT_DEVICE (device); -} - -MetaSeatImpl * -meta_input_device_native_get_seat_impl (MetaInputDeviceNative *device) -{ - return device->seat_impl; -} - -void -meta_input_device_native_update_leds_in_impl (MetaInputDeviceNative *device, - enum libinput_led leds) -{ - if (!device->libinput_device) - return; - - libinput_device_led_update (device->libinput_device, leds); -} - -ClutterInputDeviceType -meta_input_device_native_determine_type_in_impl (struct libinput_device *ldev) -{ - /* This setting is specific to touchpads and alike, only in these - * devices there is this additional layer of touch event interpretation. - */ - if (libinput_device_config_tap_get_finger_count (ldev) > 0) - return CLUTTER_TOUCHPAD_DEVICE; - else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) - return CLUTTER_TABLET_DEVICE; - else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) - return CLUTTER_PAD_DEVICE; - else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_POINTER)) - return CLUTTER_POINTER_DEVICE; - else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TOUCH)) - return CLUTTER_TOUCHSCREEN_DEVICE; - else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_KEYBOARD)) - return CLUTTER_KEYBOARD_DEVICE; - else - return CLUTTER_EXTENSION_DEVICE; -} - -/** - * meta_input_device_native_get_libinput_device: - * @device: a #ClutterInputDevice - * - * Retrieves the libinput_device struct held in @device. - * - * Returns: The libinput_device struct - * - * Since: 1.20 - * Stability: unstable - **/ -struct libinput_device * -meta_input_device_native_get_libinput_device (ClutterInputDevice *device) -{ - MetaInputDeviceNative *device_evdev; - - g_return_val_if_fail (META_IS_INPUT_DEVICE_NATIVE (device), NULL); - - device_evdev = META_INPUT_DEVICE_NATIVE (device); - - return device_evdev->libinput_device; -} - -void -meta_input_device_native_translate_coordinates_in_impl (ClutterInputDevice *device, - MetaViewportInfo *viewports, - float *x, - float *y) -{ - MetaInputDeviceNative *device_evdev = META_INPUT_DEVICE_NATIVE (device); - double min_x = 0, min_y = 0, max_x = 1, max_y = 1; - float stage_width, stage_height; - double x_d, y_d; - - meta_viewport_info_get_extents (viewports, &stage_width, &stage_height); - x_d = *x / stage_width; - y_d = *y / stage_height; - - /* Apply aspect ratio */ - if (device_evdev->output_ratio > 0 && - device_evdev->device_aspect_ratio > 0) - { - double ratio = device_evdev->device_aspect_ratio / device_evdev->output_ratio; - - if (ratio > 1) - x_d *= ratio; - else if (ratio < 1) - y_d *= 1 / ratio; - } - - cairo_matrix_transform_point (&device_evdev->device_matrix, &min_x, &min_y); - cairo_matrix_transform_point (&device_evdev->device_matrix, &max_x, &max_y); - cairo_matrix_transform_point (&device_evdev->device_matrix, &x_d, &y_d); - - *x = CLAMP (x_d, MIN (min_x, max_x), MAX (min_x, max_x)) * stage_width; - *y = CLAMP (y_d, MIN (min_y, max_y), MAX (min_y, max_y)) * stage_height; -} - -MetaInputDeviceMapping -meta_input_device_native_get_mapping_mode_in_impl (ClutterInputDevice *device) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - ClutterInputDeviceType device_type; - - g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), - META_INPUT_DEVICE_MAPPING_ABSOLUTE); - - device_type = clutter_input_device_get_device_type (device); - g_return_val_if_fail (device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_ERASER_DEVICE, - META_INPUT_DEVICE_MAPPING_ABSOLUTE); - - return device_native->mapping_mode; -} - -void -meta_input_device_native_set_mapping_mode_in_impl (ClutterInputDevice *device, - MetaInputDeviceMapping mapping) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - ClutterInputDeviceType device_type; - - g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); - - device_type = clutter_input_device_get_device_type (device); - g_return_if_fail (device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_ERASER_DEVICE); - - device_native->mapping_mode = mapping; -} - -void -meta_input_device_native_set_coords_in_impl (MetaInputDeviceNative *device_native, - float x, - float y) -{ - device_native->pointer_x = x; - device_native->pointer_y = y; -} - -void -meta_input_device_native_get_coords_in_impl (MetaInputDeviceNative *device_native, - float *x, - float *y) -{ - if (x) - *x = device_native->pointer_x; - if (y) - *y = device_native->pointer_y; -} - -void -meta_input_device_native_detach_libinput_in_impl (MetaInputDeviceNative *device_native) -{ - g_clear_pointer (&device_native->libinput_device, libinput_device_unref); -} diff --git a/src/backends/native/meta-input-device-native.h b/src/backends/native/meta-input-device-native.h deleted file mode 100644 index 88af07c43..000000000 --- a/src/backends/native/meta-input-device-native.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Damien Lespiau <damien.lespiau@intel.com> - * Author: Jonas Ådahl <jadahl@gmail.com> - */ - -#ifndef META_INPUT_DEVICE_NATIVE_H -#define META_INPUT_DEVICE_NATIVE_H - -#ifndef META_INPUT_THREAD_H_INSIDE -#error "This header cannot be included directly. Use "backends/native/meta-input-thread.h"" -#endif /* META_INPUT_THREAD_H_INSIDE */ - -#include <glib-object.h> - -#include "backends/meta-input-device-private.h" -#include "backends/meta-input-settings-private.h" -#include "backends/native/meta-seat-native.h" -#include "clutter/clutter-mutter.h" - -#define META_TYPE_INPUT_DEVICE_NATIVE meta_input_device_native_get_type() - -#define META_INPUT_DEVICE_NATIVE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - META_TYPE_INPUT_DEVICE_NATIVE, MetaInputDeviceNative)) - -#define META_INPUT_DEVICE_NATIVE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - META_TYPE_INPUT_DEVICE_NATIVE, MetaInputDeviceNativeClass)) - -#define META_IS_INPUT_DEVICE_NATIVE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - META_TYPE_INPUT_DEVICE_NATIVE)) - -#define META_IS_INPUT_DEVICE_NATIVE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - META_TYPE_INPUT_DEVICE_NATIVE)) - -#define META_INPUT_DEVICE_NATIVE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - META_TYPE_INPUT_DEVICE_NATIVE, MetaInputDeviceNativeClass)) - -typedef enum -{ - META_INPUT_DEVICE_MAPPING_ABSOLUTE, - META_INPUT_DEVICE_MAPPING_RELATIVE, -} MetaInputDeviceMapping; - -typedef struct _MetaInputDeviceNative MetaInputDeviceNative; -typedef struct _MetaInputDeviceNativeClass MetaInputDeviceNativeClass; - -struct _MetaInputDeviceNative -{ - ClutterInputDevice parent; - - struct libinput_device *libinput_device; - MetaSeatImpl *seat_impl; - ClutterInputDeviceTool *last_tool; - GArray *pad_features; - GArray *modes; - intptr_t group; - - cairo_matrix_t device_matrix; - double device_aspect_ratio; /* w:h */ - double output_ratio; /* w:h */ - MetaInputDeviceMapping mapping_mode; - - /* Pointer position */ - float pointer_x; - float pointer_y; - - /* Keyboard a11y */ - MetaKeyboardA11yFlags a11y_flags; - GList *slow_keys_list; - GSource *debounce_timer; - uint16_t debounce_key; - xkb_mod_mask_t stickykeys_depressed_mask; - xkb_mod_mask_t stickykeys_latched_mask; - xkb_mod_mask_t stickykeys_locked_mask; - GSource *toggle_slowkeys_timer; - uint16_t shift_count; - uint32_t last_shift_time; - int mousekeys_btn; - gboolean mousekeys_btn_states[3]; - uint32_t mousekeys_first_motion_time; /* ms */ - uint32_t mousekeys_last_motion_time; /* ms */ - guint mousekeys_init_delay; - guint mousekeys_accel_time; - guint mousekeys_max_speed; - double mousekeys_curve_factor; - GSource *move_mousekeys_timer; - uint16_t last_mousekeys_key; -}; - -struct _MetaInputDeviceNativeClass -{ - ClutterInputDeviceClass parent_class; -}; - -GType meta_input_device_native_get_type (void) G_GNUC_CONST; - -ClutterInputDevice * meta_input_device_native_new_in_impl (MetaSeatImpl *seat_impl, - struct libinput_device *libinput_device); - -ClutterInputDevice * meta_input_device_native_new_virtual (MetaSeatImpl *seat_impl, - ClutterInputDeviceType type, - ClutterInputMode mode); - -MetaSeatImpl * meta_input_device_native_get_seat_impl (MetaInputDeviceNative *device); - -void meta_input_device_native_update_leds_in_impl (MetaInputDeviceNative *device, - enum libinput_led leds); - -ClutterInputDeviceType meta_input_device_native_determine_type_in_impl (struct libinput_device *libinput_device); - - -void meta_input_device_native_translate_coordinates_in_impl (ClutterInputDevice *device, - MetaViewportInfo *viewports, - float *x, - float *y); - -MetaInputDeviceMapping meta_input_device_native_get_mapping_mode_in_impl (ClutterInputDevice *device); -void meta_input_device_native_set_mapping_mode_in_impl (ClutterInputDevice *device, - MetaInputDeviceMapping mapping); - -void meta_input_device_native_apply_kbd_a11y_settings_in_impl (MetaInputDeviceNative *device, - MetaKbdA11ySettings *settings); - -void meta_input_device_native_a11y_maybe_notify_toggle_keys_in_impl (MetaInputDeviceNative *device_evdev); - -struct libinput_device * meta_input_device_native_get_libinput_device (ClutterInputDevice *device); - -void meta_input_device_native_set_coords_in_impl (MetaInputDeviceNative *device_native, - float x, - float y); -void meta_input_device_native_get_coords_in_impl (MetaInputDeviceNative *device_native, - float *x, - float *y); -gboolean meta_input_device_native_process_kbd_a11y_event_in_impl (ClutterInputDevice *device, - ClutterEvent *event); -void meta_input_device_native_detach_libinput_in_impl (MetaInputDeviceNative *device_native); - -#endif /* META_INPUT_DEVICE_NATIVE_H */ diff --git a/src/backends/native/meta-input-device-tool-native.c b/src/backends/native/meta-input-device-tool-native.c deleted file mode 100644 index e6ec0c758..000000000 --- a/src/backends/native/meta-input-device-tool-native.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright © 2009, 2010, 2011 Intel Corp. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Carlos Garnacho <carlosg@gnome.org> - */ - -#include "config.h" - -#include "backends/native/meta-input-thread.h" - -G_DEFINE_TYPE (MetaInputDeviceToolNative, meta_input_device_tool_native, - CLUTTER_TYPE_INPUT_DEVICE_TOOL) - -static void -meta_input_device_tool_native_finalize (GObject *object) -{ - MetaInputDeviceToolNative *tool = META_INPUT_DEVICE_TOOL_NATIVE (object); - - g_hash_table_unref (tool->button_map); - libinput_tablet_tool_unref (tool->tool); - - G_OBJECT_CLASS (meta_input_device_tool_native_parent_class)->finalize (object); -} - -static void -meta_input_device_tool_native_class_init (MetaInputDeviceToolNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_input_device_tool_native_finalize; -} - -static void -meta_input_device_tool_native_init (MetaInputDeviceToolNative *tool) -{ - tool->button_map = g_hash_table_new (NULL, NULL); -} - -static ClutterInputAxisFlags -translate_axes (struct libinput_tablet_tool *tool) -{ - ClutterInputAxisFlags axes = 0; - - if (libinput_tablet_tool_has_pressure (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_PRESSURE; - if (libinput_tablet_tool_has_distance (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_DISTANCE; - if (libinput_tablet_tool_has_rotation (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_ROTATION; - if (libinput_tablet_tool_has_slider (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_SLIDER; - if (libinput_tablet_tool_has_wheel (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_WHEEL; - if (libinput_tablet_tool_has_tilt (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_XTILT | CLUTTER_INPUT_AXIS_FLAG_YTILT; - - return axes; -} - -ClutterInputDeviceTool * -meta_input_device_tool_native_new (struct libinput_tablet_tool *tool, - uint64_t serial, - ClutterInputDeviceToolType type) -{ - MetaInputDeviceToolNative *evdev_tool; - - evdev_tool = g_object_new (META_TYPE_INPUT_DEVICE_TOOL_NATIVE, - "type", type, - "serial", serial, - "id", libinput_tablet_tool_get_tool_id (tool), - "axes", translate_axes (tool), - NULL); - - evdev_tool->tool = libinput_tablet_tool_ref (tool); - - return CLUTTER_INPUT_DEVICE_TOOL (evdev_tool); -} - -void -meta_input_device_tool_native_set_pressure_curve_in_impl (ClutterInputDeviceTool *tool, - double curve[4]) -{ - MetaInputDeviceToolNative *evdev_tool; - - g_return_if_fail (META_IS_INPUT_DEVICE_TOOL_NATIVE (tool)); - g_return_if_fail (curve[0] >= 0 && curve[0] <= 1 && - curve[1] >= 0 && curve[1] <= 1 && - curve[2] >= 0 && curve[2] <= 1 && - curve[3] >= 0 && curve[3] <= 1); - - evdev_tool = META_INPUT_DEVICE_TOOL_NATIVE (tool); - evdev_tool->pressure_curve[0] = curve[0]; - evdev_tool->pressure_curve[1] = curve[1]; - evdev_tool->pressure_curve[2] = curve[2]; - evdev_tool->pressure_curve[3] = curve[3]; -} - -void -meta_input_device_tool_native_set_button_code_in_impl (ClutterInputDeviceTool *tool, - uint32_t button, - uint32_t evcode) -{ - MetaInputDeviceToolNative *evdev_tool; - - g_return_if_fail (META_IS_INPUT_DEVICE_TOOL_NATIVE (tool)); - - evdev_tool = META_INPUT_DEVICE_TOOL_NATIVE (tool); - - if (evcode == 0) - { - g_hash_table_remove (evdev_tool->button_map, GUINT_TO_POINTER (button)); - } - else - { - g_hash_table_insert (evdev_tool->button_map, GUINT_TO_POINTER (button), - GUINT_TO_POINTER (evcode)); - } -} - -static double -calculate_bezier_position (double pos, - double x1, - double y1, - double x2, - double y2) -{ - double int1_y, int2_y; - - pos = CLAMP (pos, 0, 1); - - /* Intersection between 0,0 and x1,y1 */ - int1_y = pos * y1; - - /* Intersection between x2,y2 and 1,1 */ - int2_y = (pos * (1 - y2)) + y2; - - /* Find the new position in the line traced by the previous points */ - return (pos * (int2_y - int1_y)) + int1_y; -} - -double -meta_input_device_tool_native_translate_pressure_in_impl (ClutterInputDeviceTool *tool, - double pressure) -{ - MetaInputDeviceToolNative *evdev_tool; - - g_return_val_if_fail (META_IS_INPUT_DEVICE_TOOL_NATIVE (tool), pressure); - - evdev_tool = META_INPUT_DEVICE_TOOL_NATIVE (tool); - - return calculate_bezier_position (CLAMP (pressure, 0, 1), - evdev_tool->pressure_curve[0], - evdev_tool->pressure_curve[1], - evdev_tool->pressure_curve[2], - evdev_tool->pressure_curve[3]); -} - -uint32_t -meta_input_device_tool_native_get_button_code_in_impl (ClutterInputDeviceTool *tool, - uint32_t button) -{ - MetaInputDeviceToolNative *evdev_tool; - - g_return_val_if_fail (META_IS_INPUT_DEVICE_TOOL_NATIVE (tool), 0); - - evdev_tool = META_INPUT_DEVICE_TOOL_NATIVE (tool); - - return GPOINTER_TO_UINT (g_hash_table_lookup (evdev_tool->button_map, - GUINT_TO_POINTER (button))); -} diff --git a/src/backends/native/meta-input-device-tool-native.h b/src/backends/native/meta-input-device-tool-native.h deleted file mode 100644 index fa12358ad..000000000 --- a/src/backends/native/meta-input-device-tool-native.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright © 2009, 2010, 2011 Intel Corp. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Carlos Garnacho <carlosg@gnome.org> - */ - -#ifndef META_INPUT_DEVICE_NATIVE_TOOL_H -#define META_INPUT_DEVICE_NATIVE_TOOL_H - -#ifndef META_INPUT_THREAD_H_INSIDE -#error "This header cannot be included directly. Use "backends/native/meta-input-thread.h"" -#endif /* META_INPUT_THREAD_H_INSIDE */ - -#include <libinput.h> - -#include "clutter/clutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_INPUT_DEVICE_TOOL_NATIVE (meta_input_device_tool_native_get_type ()) - -#define META_INPUT_DEVICE_TOOL_NATIVE(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), \ - META_TYPE_INPUT_DEVICE_TOOL_NATIVE, MetaInputDeviceToolNative)) - -#define META_IS_INPUT_DEVICE_TOOL_NATIVE(o) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ - META_TYPE_INPUT_DEVICE_TOOL_NATIVE)) - -#define META_INPUT_DEVICE_TOOL_NATIVE_CLASS(c) \ - (G_TYPE_CHECK_CLASS_CAST ((c), \ - META_TYPE_INPUT_DEVICE_TOOL_EVDEV, MetaInputDeviceToolNativeClass)) - -#define META_IS_INPUT_DEVICE_TOOL_NATIVE_CLASS(c) \ - (G_TYPE_CHECK_CLASS_TYPE ((c), \ - META_TYPE_INPUT_DEVICE_TOOL_NATIVE)) - -#define META_INPUT_DEVICE_TOOL_NATIVE_GET_CLASS(o) \ - (G_TYPE_INSTANCE_GET_CLASS ((o), \ - META_TYPE_INPUT_DEVICE_TOOL_NATIVE, MetaInputDeviceToolNativeClass)) - -typedef struct _MetaInputDeviceToolNative MetaInputDeviceToolNative; -typedef struct _MetaInputDeviceToolNativeClass MetaInputDeviceToolNativeClass; - -struct _MetaInputDeviceToolNative -{ - ClutterInputDeviceTool parent_instance; - struct libinput_tablet_tool *tool; - GHashTable *button_map; - double pressure_curve[4]; -}; - -struct _MetaInputDeviceToolNativeClass -{ - ClutterInputDeviceToolClass parent_class; -}; - -GType meta_input_device_tool_native_get_type (void) G_GNUC_CONST; - -ClutterInputDeviceTool * meta_input_device_tool_native_new (struct libinput_tablet_tool *tool, - uint64_t serial, - ClutterInputDeviceToolType type); - -gdouble meta_input_device_tool_native_translate_pressure_in_impl (ClutterInputDeviceTool *tool, - double pressure); -uint32_t meta_input_device_tool_native_get_button_code_in_impl (ClutterInputDeviceTool *tool, - uint32_t button); - -void meta_input_device_tool_native_set_pressure_curve_in_impl (ClutterInputDeviceTool *tool, - double curve[4]); -void meta_input_device_tool_native_set_button_code_in_impl (ClutterInputDeviceTool *tool, - uint32_t button, - uint32_t evcode); - -G_END_DECLS - -#endif /* META_INPUT_DEVICE_NATIVE_TOOL_H */ diff --git a/src/backends/native/meta-input-settings-native.c b/src/backends/native/meta-input-settings-native.c deleted file mode 100644 index 8f61b8bcc..000000000 --- a/src/backends/native/meta-input-settings-native.c +++ /dev/null @@ -1,876 +0,0 @@ -/* -*- 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. - * - * Author: Carlos Garnacho <carlosg@gnome.org> - */ - -#include "config.h" - -#include <linux/input-event-codes.h> -#include <libinput.h> - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-input-settings-native.h" - -G_DEFINE_TYPE (MetaInputSettingsNative, meta_input_settings_native, META_TYPE_INPUT_SETTINGS) - -enum -{ - PROP_0, - PROP_SEAT_IMPL, - N_PROPS, -}; - -static GParamSpec *props[N_PROPS] = { 0 }; - -static void -meta_input_settings_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaInputSettingsNative *input_settings_native = - META_INPUT_SETTINGS_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT_IMPL: - input_settings_native->seat_impl = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_input_settings_native_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaInputSettingsNative *input_settings_native = - META_INPUT_SETTINGS_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT_IMPL: - g_value_set_object (value, input_settings_native->seat_impl); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -set_send_events (GTask *task) -{ - GDesktopDeviceSendEvents mode; - ClutterInputDevice *device; - enum libinput_config_send_events_mode libinput_mode; - struct libinput_device *libinput_device; - - device = g_task_get_source_object (task); - mode = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - switch (mode) - { - case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED: - libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; - break; - case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE: - libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; - break; - case G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED: - libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; - break; - default: - g_assert_not_reached (); - } - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (libinput_device) - libinput_device_config_send_events_set_mode (libinput_device, libinput_mode); - - return G_SOURCE_REMOVE; -} - -static void -meta_input_settings_native_set_send_events (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopDeviceSendEvents mode) -{ - MetaInputSettingsNative *input_settings_native; - GTask *task; - - task = g_task_new (device, NULL, NULL, NULL); - g_task_set_task_data (task, GUINT_TO_POINTER (mode), NULL); - - input_settings_native = META_INPUT_SETTINGS_NATIVE (settings); - meta_seat_impl_run_input_task (input_settings_native->seat_impl, - task, (GSourceFunc) set_send_events); - g_object_unref (task); -} - -static gboolean -set_matrix (GTask *task) -{ - ClutterInputDevice *device = g_task_get_source_object (task); - float *matrix = g_task_get_task_data (task); - cairo_matrix_t dev_matrix; - - if (clutter_input_device_get_device_type (device) == - CLUTTER_TOUCHSCREEN_DEVICE || - meta_input_device_native_get_mapping_mode_in_impl (device) == - META_INPUT_DEVICE_MAPPING_ABSOLUTE) - { - cairo_matrix_init (&dev_matrix, - matrix[0], matrix[3], matrix[1], - matrix[4], matrix[2], matrix[5]); - } - else - { - cairo_matrix_init_identity (&dev_matrix); - } - - g_object_set (device, "device-matrix", &dev_matrix, NULL); - - return G_SOURCE_REMOVE; -} - -static void -meta_input_settings_native_set_matrix (MetaInputSettings *settings, - ClutterInputDevice *device, - const float matrix[6]) -{ - MetaInputSettingsNative *input_settings_native; - GTask *task; - - task = g_task_new (device, NULL, NULL, NULL); - - g_task_set_task_data (task, g_memdup2 (matrix, sizeof (float) * 6), g_free); - - input_settings_native = META_INPUT_SETTINGS_NATIVE (settings); - meta_seat_impl_run_input_task (input_settings_native->seat_impl, - task, (GSourceFunc) set_matrix); - g_object_unref (task); -} - -static void -meta_input_settings_native_set_speed (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble speed) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - libinput_device_config_accel_set_speed (libinput_device, - CLAMP (speed, -1, 1)); -} - -static void -meta_input_settings_native_set_left_handed (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_left_handed_is_available (libinput_device)) - libinput_device_config_left_handed_set (libinput_device, enabled); -} - -static void -meta_input_settings_native_set_tap_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_tap_get_finger_count (libinput_device) > 0) - libinput_device_config_tap_set_enabled (libinput_device, - enabled ? - LIBINPUT_CONFIG_TAP_ENABLED : - LIBINPUT_CONFIG_TAP_DISABLED); -} - -static void -meta_input_settings_native_set_tap_and_drag_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_tap_get_finger_count (libinput_device) > 0) - libinput_device_config_tap_set_drag_enabled (libinput_device, - enabled ? - LIBINPUT_CONFIG_DRAG_ENABLED : - LIBINPUT_CONFIG_DRAG_DISABLED); -} - -static void -meta_input_settings_native_set_tap_and_drag_lock_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_tap_get_finger_count (libinput_device) > 0) - libinput_device_config_tap_set_drag_lock_enabled (libinput_device, - enabled ? - LIBINPUT_CONFIG_DRAG_LOCK_ENABLED : - LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); -} - -static void -meta_input_settings_native_set_disable_while_typing (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - - if (!libinput_device) - return; - - if (libinput_device_config_dwt_is_available (libinput_device)) - libinput_device_config_dwt_set_enabled (libinput_device, - enabled ? - LIBINPUT_CONFIG_DWT_ENABLED : - LIBINPUT_CONFIG_DWT_DISABLED); -} - -static void -meta_input_settings_native_set_invert_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean inverted) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_scroll_has_natural_scroll (libinput_device)) - libinput_device_config_scroll_set_natural_scroll_enabled (libinput_device, - inverted); -} - -static gboolean -device_set_scroll_method (struct libinput_device *libinput_device, - enum libinput_config_scroll_method method) -{ - enum libinput_config_status status = - libinput_device_config_scroll_set_method (libinput_device, method); - return status == LIBINPUT_CONFIG_STATUS_SUCCESS; -} - -static gboolean -device_set_click_method (struct libinput_device *libinput_device, - enum libinput_config_click_method method) -{ - enum libinput_config_status status = - libinput_device_config_click_set_method (libinput_device, method); - return status == LIBINPUT_CONFIG_STATUS_SUCCESS; -} - -static gboolean -device_set_tap_button_map (struct libinput_device *libinput_device, - enum libinput_config_tap_button_map map) -{ - enum libinput_config_status status = - libinput_device_config_tap_set_button_map (libinput_device, map); - return status == LIBINPUT_CONFIG_STATUS_SUCCESS; -} - -static void -meta_input_settings_native_set_edge_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean edge_scrolling_enabled) -{ - struct libinput_device *libinput_device; - enum libinput_config_scroll_method current, method; - - libinput_device = meta_input_device_native_get_libinput_device (device); - - method = edge_scrolling_enabled ? LIBINPUT_CONFIG_SCROLL_EDGE : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; - current = libinput_device_config_scroll_get_method (libinput_device); - current &= ~LIBINPUT_CONFIG_SCROLL_EDGE; - - device_set_scroll_method (libinput_device, current | method); -} - -static void -meta_input_settings_native_set_two_finger_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean two_finger_scroll_enabled) -{ - struct libinput_device *libinput_device; - enum libinput_config_scroll_method current, method; - - libinput_device = meta_input_device_native_get_libinput_device (device); - - method = two_finger_scroll_enabled ? LIBINPUT_CONFIG_SCROLL_2FG : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; - current = libinput_device_config_scroll_get_method (libinput_device); - current &= ~LIBINPUT_CONFIG_SCROLL_2FG; - - device_set_scroll_method (libinput_device, current | method); -} - -static gboolean -meta_input_settings_native_has_two_finger_scroll (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return FALSE; - - return libinput_device_config_scroll_get_methods (libinput_device) & LIBINPUT_CONFIG_SCROLL_2FG; -} - -static void -meta_input_settings_native_set_scroll_button (MetaInputSettings *settings, - ClutterInputDevice *device, - guint button, - gboolean button_lock) -{ - struct libinput_device *libinput_device; - enum libinput_config_scroll_method method; - enum libinput_config_scroll_button_lock_state lock_state; - guint evcode; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (button == 0) - { - method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; - evcode = 0; - } - else - { - switch (button) - { - case 1: - evcode = BTN_LEFT; - break; - case 2: - evcode = BTN_MIDDLE; - break; - case 3: - evcode = BTN_RIGHT; - break; - default: - /* Compensate for X11 scroll buttons */ - if (button > 7) - button -= 4; - - /* Button is 1-indexed */ - evcode = (BTN_LEFT - 1) + button; - } - - method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; - } - - if (!device_set_scroll_method (libinput_device, method)) - return; - - libinput_device_config_scroll_set_button (libinput_device, evcode); - - if (button_lock) - lock_state = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED; - else - lock_state = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED; - - libinput_device_config_scroll_set_button_lock (libinput_device, lock_state); -} - -static void -meta_input_settings_native_set_click_method (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTouchpadClickMethod mode) -{ - enum libinput_config_click_method click_method = 0; - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - switch (mode) - { - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT: - click_method = libinput_device_config_click_get_default_method (libinput_device); - break; - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE: - click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE; - break; - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS: - click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; - break; - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS: - click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; - break; - default: - g_assert_not_reached (); - return; - } - - device_set_click_method (libinput_device, click_method); -} - -static void -meta_input_settings_native_set_tap_button_map (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTouchpadTapButtonMap mode) -{ - enum libinput_config_tap_button_map button_map = 0; - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_tap_get_finger_count (libinput_device) == 0) - return; - - switch (mode) - { - case G_DESKTOP_TOUCHPAD_BUTTON_TAP_MAP_DEFAULT: - button_map = libinput_device_config_tap_get_default_button_map (libinput_device); - break; - case G_DESKTOP_TOUCHPAD_BUTTON_TAP_MAP_LRM: - button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; - break; - case G_DESKTOP_TOUCHPAD_BUTTON_TAP_MAP_LMR: - button_map = LIBINPUT_CONFIG_TAP_MAP_LMR; - break; - default: - g_assert_not_reached (); - return; - } - - device_set_tap_button_map (libinput_device, button_map); -} - -static void -meta_input_settings_native_set_keyboard_repeat (MetaInputSettings *settings, - gboolean enabled, - guint delay, - guint interval) -{ - MetaInputSettingsNative *input_settings_native; - - input_settings_native = META_INPUT_SETTINGS_NATIVE (settings); - meta_seat_impl_set_keyboard_repeat_in_impl (input_settings_native->seat_impl, - enabled, delay, interval); -} - -static void -set_device_accel_profile (ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ - struct libinput_device *libinput_device; - enum libinput_config_accel_profile libinput_profile; - uint32_t profiles; - - libinput_device = meta_input_device_native_get_libinput_device (device); - - switch (profile) - { - case G_DESKTOP_POINTER_ACCEL_PROFILE_FLAT: - libinput_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; - break; - case G_DESKTOP_POINTER_ACCEL_PROFILE_ADAPTIVE: - libinput_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; - break; - default: - g_warn_if_reached (); - case G_DESKTOP_POINTER_ACCEL_PROFILE_DEFAULT: - libinput_profile = - libinput_device_config_accel_get_default_profile (libinput_device); - } - - profiles = libinput_device_config_accel_get_profiles (libinput_device); - if ((profiles & libinput_profile) == 0) - { - libinput_profile = - libinput_device_config_accel_get_default_profile (libinput_device); - } - - libinput_device_config_accel_set_profile (libinput_device, - libinput_profile); -} - -static gboolean -has_udev_property (ClutterInputDevice *device, - const char *property) -{ - struct libinput_device *libinput_device; - struct udev_device *udev_device; - struct udev_device *parent_udev_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return FALSE; - - udev_device = libinput_device_get_udev_device (libinput_device); - - if (!udev_device) - return FALSE; - - if (NULL != udev_device_get_property_value (udev_device, property)) - { - udev_device_unref (udev_device); - return TRUE; - } - - parent_udev_device = udev_device_get_parent (udev_device); - udev_device_unref (udev_device); - - if (!parent_udev_device) - return FALSE; - - if (NULL != udev_device_get_property_value (parent_udev_device, property)) - return TRUE; - - return FALSE; -} - -static gboolean -is_mouse_device (ClutterInputDevice *device) -{ - return (has_udev_property (device, "ID_INPUT_MOUSE") && - !has_udev_property (device, "ID_INPUT_POINTINGSTICK")); -} - -static gboolean -meta_input_settings_native_is_touchpad_device (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - return has_udev_property (device, "ID_INPUT_TOUCHPAD"); -} - -static gboolean -meta_input_settings_native_is_trackball_device (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - return has_udev_property (device, "ID_INPUT_TRACKBALL"); -} - -static void -meta_input_settings_native_set_mouse_accel_profile (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ - if (!is_mouse_device (device)) - return; - - set_device_accel_profile (device, profile); -} - -static void -meta_input_settings_native_set_trackball_accel_profile (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ - if (!meta_input_settings_native_is_trackball_device (settings, device)) - return; - - set_device_accel_profile (device, profile); -} - -static void -meta_input_settings_native_set_tablet_mapping (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTabletMapping mapping) -{ - MetaInputDeviceMapping dev_mapping; - - if (mapping == G_DESKTOP_TABLET_MAPPING_ABSOLUTE) - dev_mapping = META_INPUT_DEVICE_MAPPING_ABSOLUTE; - else if (mapping == G_DESKTOP_TABLET_MAPPING_RELATIVE) - dev_mapping = META_INPUT_DEVICE_MAPPING_RELATIVE; - else - return; - - meta_input_device_native_set_mapping_mode_in_impl (device, dev_mapping); -} - -static gboolean -set_tablet_aspect_ratio (GTask *task) -{ - ClutterInputDevice *device; - double *aspect_ratio; - - device = g_task_get_source_object (task); - aspect_ratio = g_task_get_task_data (task); - g_object_set (device, "output-aspect-ratio", *aspect_ratio, NULL); - - return G_SOURCE_REMOVE; -} - -static void -meta_input_settings_native_set_tablet_aspect_ratio (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble aspect_ratio) -{ - MetaInputSettingsNative *input_settings_native; - GTask *task; - - if (meta_input_device_native_get_mapping_mode_in_impl (device) == - META_INPUT_DEVICE_MAPPING_RELATIVE) - aspect_ratio = 0; - - task = g_task_new (device, NULL, NULL, NULL); - g_task_set_task_data (task, - g_memdup2 (&aspect_ratio, sizeof (double)), - g_free); - - input_settings_native = META_INPUT_SETTINGS_NATIVE (settings); - meta_seat_impl_run_input_task (input_settings_native->seat_impl, - task, (GSourceFunc) set_tablet_aspect_ratio); - g_object_unref (task); -} - -static void -meta_input_settings_native_set_tablet_area (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble padding_left, - gdouble padding_right, - gdouble padding_top, - gdouble padding_bottom) -{ - struct libinput_device *libinput_device; - gfloat scale_x; - gfloat scale_y; - gfloat offset_x; - gfloat offset_y; - - scale_x = 1. / (1. - (padding_left + padding_right)); - scale_y = 1. / (1. - (padding_top + padding_bottom)); - offset_x = -padding_left * scale_x; - offset_y = -padding_top * scale_y; - - gfloat matrix[6] = { scale_x, 0., offset_x, - 0., scale_y, offset_y }; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device || - !libinput_device_config_calibration_has_matrix (libinput_device)) - return; - - libinput_device_config_calibration_set_matrix (libinput_device, matrix); -} - -static void -meta_input_settings_native_set_stylus_pressure (MetaInputSettings *settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - const gint curve[4]) -{ - gdouble pressure_curve[4]; - - pressure_curve[0] = (gdouble) curve[0] / 100; - pressure_curve[1] = (gdouble) curve[1] / 100; - pressure_curve[2] = (gdouble) curve[2] / 100; - pressure_curve[3] = (gdouble) curve[3] / 100; - - meta_input_device_tool_native_set_pressure_curve_in_impl (tool, pressure_curve); -} - -static guint -action_to_evcode (GDesktopStylusButtonAction action) -{ - switch (action) - { - case G_DESKTOP_STYLUS_BUTTON_ACTION_MIDDLE: - return BTN_STYLUS; - case G_DESKTOP_STYLUS_BUTTON_ACTION_RIGHT: - return BTN_STYLUS2; - case G_DESKTOP_STYLUS_BUTTON_ACTION_BACK: - return BTN_BACK; - case G_DESKTOP_STYLUS_BUTTON_ACTION_FORWARD: - return BTN_FORWARD; - case G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT: - default: - return 0; - } -} - -static void -meta_input_settings_native_set_stylus_button_map (MetaInputSettings *settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - GDesktopStylusButtonAction primary, - GDesktopStylusButtonAction secondary, - GDesktopStylusButtonAction tertiary) -{ - meta_input_device_tool_native_set_button_code_in_impl (tool, CLUTTER_BUTTON_MIDDLE, - action_to_evcode (primary)); - meta_input_device_tool_native_set_button_code_in_impl (tool, CLUTTER_BUTTON_SECONDARY, - action_to_evcode (secondary)); - meta_input_device_tool_native_set_button_code_in_impl (tool, 8, /* Back */ - action_to_evcode (tertiary)); -} - -static void -meta_input_settings_native_set_mouse_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - if (!is_mouse_device (device)) - return; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_middle_emulation_is_available (libinput_device)) - libinput_device_config_middle_emulation_set_enabled (libinput_device, enabled); -} - -static void -meta_input_settings_native_set_touchpad_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - if (!meta_input_settings_native_is_touchpad_device (settings, device)) - return; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_middle_emulation_is_available (libinput_device)) - libinput_device_config_middle_emulation_set_enabled (libinput_device, enabled); -} - -static void -meta_input_settings_native_set_trackball_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - if (!meta_input_settings_native_is_trackball_device (settings, device)) - return; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_middle_emulation_is_available (libinput_device)) - libinput_device_config_middle_emulation_set_enabled (libinput_device, enabled); -} - -static void -meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass) -{ - MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_input_settings_native_set_property; - object_class->get_property = meta_input_settings_native_get_property; - - input_settings_class->set_send_events = meta_input_settings_native_set_send_events; - input_settings_class->set_matrix = meta_input_settings_native_set_matrix; - input_settings_class->set_speed = meta_input_settings_native_set_speed; - input_settings_class->set_left_handed = meta_input_settings_native_set_left_handed; - input_settings_class->set_tap_enabled = meta_input_settings_native_set_tap_enabled; - input_settings_class->set_tap_button_map = meta_input_settings_native_set_tap_button_map; - input_settings_class->set_tap_and_drag_enabled = meta_input_settings_native_set_tap_and_drag_enabled; - input_settings_class->set_tap_and_drag_lock_enabled = - meta_input_settings_native_set_tap_and_drag_lock_enabled; - input_settings_class->set_invert_scroll = meta_input_settings_native_set_invert_scroll; - input_settings_class->set_edge_scroll = meta_input_settings_native_set_edge_scroll; - input_settings_class->set_two_finger_scroll = meta_input_settings_native_set_two_finger_scroll; - input_settings_class->set_scroll_button = meta_input_settings_native_set_scroll_button; - input_settings_class->set_click_method = meta_input_settings_native_set_click_method; - input_settings_class->set_keyboard_repeat = meta_input_settings_native_set_keyboard_repeat; - input_settings_class->set_disable_while_typing = meta_input_settings_native_set_disable_while_typing; - - input_settings_class->set_tablet_mapping = meta_input_settings_native_set_tablet_mapping; - input_settings_class->set_tablet_aspect_ratio = meta_input_settings_native_set_tablet_aspect_ratio; - input_settings_class->set_tablet_area = meta_input_settings_native_set_tablet_area; - - input_settings_class->set_mouse_accel_profile = meta_input_settings_native_set_mouse_accel_profile; - input_settings_class->set_trackball_accel_profile = meta_input_settings_native_set_trackball_accel_profile; - - input_settings_class->set_stylus_pressure = meta_input_settings_native_set_stylus_pressure; - input_settings_class->set_stylus_button_map = meta_input_settings_native_set_stylus_button_map; - - input_settings_class->set_mouse_middle_click_emulation = meta_input_settings_native_set_mouse_middle_click_emulation; - input_settings_class->set_touchpad_middle_click_emulation = meta_input_settings_native_set_touchpad_middle_click_emulation; - input_settings_class->set_trackball_middle_click_emulation = meta_input_settings_native_set_trackball_middle_click_emulation; - - input_settings_class->has_two_finger_scroll = meta_input_settings_native_has_two_finger_scroll; - input_settings_class->is_trackball_device = meta_input_settings_native_is_trackball_device; - - props[PROP_SEAT_IMPL] = - g_param_spec_object ("seat-impl", - "Seat Impl", - "Seat Impl", - META_TYPE_SEAT_IMPL, - CLUTTER_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, N_PROPS, props); -} - -static void -meta_input_settings_native_init (MetaInputSettingsNative *settings) -{ -} - -MetaInputSettings * -meta_input_settings_native_new_in_impl (MetaSeatImpl *seat_impl) -{ - return g_object_new (META_TYPE_INPUT_SETTINGS_NATIVE, - "seat-impl", seat_impl, - NULL); -} diff --git a/src/backends/native/meta-input-settings-native.h b/src/backends/native/meta-input-settings-native.h deleted file mode 100644 index cddd5b15f..000000000 --- a/src/backends/native/meta-input-settings-native.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2014 Red Hat, Inc. - * - * 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, see <http://www.gnu.org/licenses/>. - * - * Author: Carlos Garnacho <carlosg@gnome.org> - */ - -#ifndef META_INPUT_SETTINGS_NATIVE_H -#define META_INPUT_SETTINGS_NATIVE_H - -#ifndef META_INPUT_THREAD_H_INSIDE -#error "This header cannot be included directly. Use "backends/native/meta-input-thread.h"" -#endif /* META_INPUT_THREAD_H_INSIDE */ - -#include "backends/meta-input-settings-private.h" - -#define META_TYPE_INPUT_SETTINGS_NATIVE (meta_input_settings_native_get_type ()) -#define META_INPUT_SETTINGS_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNative)) -#define META_INPUT_SETTINGS_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNativeClass)) -#define META_IS_INPUT_SETTINGS_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS_NATIVE)) -#define META_IS_INPUT_SETTINGS_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_INPUT_SETTINGS_NATIVE)) -#define META_INPUT_SETTINGS_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNativeClass)) - -typedef struct _MetaInputSettingsNative MetaInputSettingsNative; -typedef struct _MetaInputSettingsNativeClass MetaInputSettingsNativeClass; - -struct _MetaInputSettingsNative -{ - MetaInputSettings parent_instance; - MetaSeatImpl *seat_impl; -}; - -struct _MetaInputSettingsNativeClass -{ - MetaInputSettingsClass parent_class; -}; - -GType meta_input_settings_native_get_type (void) G_GNUC_CONST; - -MetaInputSettings * meta_input_settings_native_new_in_impl (MetaSeatImpl *seat_impl); - -#endif /* META_INPUT_SETTINGS_NATIVE_H */ diff --git a/src/backends/native/meta-input-thread.h b/src/backends/native/meta-input-thread.h deleted file mode 100644 index 196adc27b..000000000 --- a/src/backends/native/meta-input-thread.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2020 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Carlos Garnacho <carlosg@gnome.org> - */ - -#ifndef META_INPUT_THREAD_H -#define META_INPUT_THREAD_H - -#define META_INPUT_THREAD_H_INSIDE - -#include "src/backends/native/meta-input-device-native.h" -#include "src/backends/native/meta-input-device-tool-native.h" -#include "src/backends/native/meta-input-settings-native.h" -#include "src/backends/native/meta-keymap-native.h" -#include "src/backends/native/meta-seat-impl.h" - -#undef META_INPUT_THREAD_H_INSIDE - -#endif /* META_INPUT_THREAD_H */ diff --git a/src/backends/native/meta-keymap-native.c b/src/backends/native/meta-keymap-native.c deleted file mode 100644 index 500bb1012..000000000 --- a/src/backends/native/meta-keymap-native.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2018 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. - * - * Author: Carlos Garnacho <carlosg@gnome.org> - */ - -#include "config.h" - -#include "backends/meta-keymap-utils.h" -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-seat-impl.h" -#include "backends/native/meta-seat-native.h" -#include "clutter/clutter-keymap-private.h" - -static const char *option_xkb_layout = "us"; -static const char *option_xkb_variant = ""; -static const char *option_xkb_options = ""; - -typedef struct _MetaKeymapNative MetaKeymapNative; - -struct _MetaKeymapNative -{ - ClutterKeymap parent_instance; - - struct xkb_keymap *keymap; - gboolean num_lock; - gboolean caps_lock; -}; - -G_DEFINE_TYPE (MetaKeymapNative, meta_keymap_native, - CLUTTER_TYPE_KEYMAP) - -static void -meta_keymap_native_finalize (GObject *object) -{ - MetaKeymapNative *keymap = META_KEYMAP_NATIVE (object); - - xkb_keymap_unref (keymap->keymap); - - G_OBJECT_CLASS (meta_keymap_native_parent_class)->finalize (object); -} - -static PangoDirection -meta_keymap_native_get_direction (ClutterKeymap *keymap) -{ - return PANGO_DIRECTION_NEUTRAL; -} - -static void -meta_keymap_native_class_init (MetaKeymapNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterKeymapClass *keymap_class = CLUTTER_KEYMAP_CLASS (klass); - - object_class->finalize = meta_keymap_native_finalize; - - keymap_class->get_direction = meta_keymap_native_get_direction; -} - -static void -meta_keymap_native_init (MetaKeymapNative *keymap) -{ - struct xkb_context *ctx; - struct xkb_rule_names names; - - names.rules = "evdev"; - names.model = "pc105"; - names.layout = option_xkb_layout; - names.variant = option_xkb_variant; - names.options = option_xkb_options; - - ctx = meta_create_xkb_context (); - g_assert (ctx); - keymap->keymap = xkb_keymap_new_from_names (ctx, &names, 0); - xkb_context_unref (ctx); -} - -void -meta_keymap_native_set_keyboard_map_in_impl (MetaKeymapNative *keymap, - struct xkb_keymap *xkb_keymap) -{ - g_return_if_fail (xkb_keymap != NULL); - - if (keymap->keymap) - xkb_keymap_unref (keymap->keymap); - keymap->keymap = xkb_keymap_ref (xkb_keymap); -} - -struct xkb_keymap * -meta_keymap_native_get_keyboard_map_in_impl (MetaKeymapNative *keymap) -{ - return keymap->keymap; -} - -typedef struct -{ - MetaKeymapNative *keymap_native; - gboolean num_lock_state; - gboolean caps_lock_state; -} UpdateLockedModifierStateData; - -static gboolean -update_locked_modifier_state_in_main (gpointer user_data) -{ - UpdateLockedModifierStateData *data = user_data; - - clutter_keymap_set_lock_modifier_state (CLUTTER_KEYMAP (data->keymap_native), - data->caps_lock_state, - data->num_lock_state); - - return G_SOURCE_REMOVE; -} - -void -meta_keymap_native_update_in_impl (MetaKeymapNative *keymap_native, - MetaSeatImpl *seat_impl, - struct xkb_state *xkb_state) -{ - UpdateLockedModifierStateData *data; - - data = g_new0 (UpdateLockedModifierStateData, 1); - data->keymap_native = keymap_native; - data->num_lock_state = - xkb_state_mod_name_is_active (xkb_state, - XKB_MOD_NAME_NUM, - XKB_STATE_MODS_LATCHED | - XKB_STATE_MODS_LOCKED); - data->caps_lock_state = - xkb_state_mod_name_is_active (xkb_state, - XKB_MOD_NAME_CAPS, - XKB_STATE_MODS_LATCHED | - XKB_STATE_MODS_LOCKED); - - meta_seat_impl_queue_main_thread_idle (seat_impl, - update_locked_modifier_state_in_main, - data, g_free); -} diff --git a/src/backends/native/meta-keymap-native.h b/src/backends/native/meta-keymap-native.h deleted file mode 100644 index 0aa62d085..000000000 --- a/src/backends/native/meta-keymap-native.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2018 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. - * - * Author: Carlos Garnacho <carlosg@gnome.org> - */ -#ifndef META_KEYMAP_NATIVE_H -#define META_KEYMAP_NATIVE_H - -#ifndef META_INPUT_THREAD_H_INSIDE -#error "This header cannot be included directly. Use "backends/native/meta-input-thread.h"" -#endif /* META_INPUT_THREAD_H_INSIDE */ - -#include "backends/native/meta-xkb-utils.h" -#include "clutter/clutter.h" - -#define META_TYPE_KEYMAP_NATIVE (meta_keymap_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKeymapNative, meta_keymap_native, - META, KEYMAP_NATIVE, - ClutterKeymap) - -void meta_keymap_native_set_keyboard_map_in_impl (MetaKeymapNative *keymap, - struct xkb_keymap *xkb_keymap); -struct xkb_keymap * meta_keymap_native_get_keyboard_map_in_impl (MetaKeymapNative *keymap); -void meta_keymap_native_update_in_impl (MetaKeymapNative *keymap, - MetaSeatImpl *seat_impl, - struct xkb_state *xkb_state); - -#endif /* META_KEYMAP_NATIVE_H */ diff --git a/src/backends/native/meta-kms-connector-private.h b/src/backends/native/meta-kms-connector-private.h deleted file mode 100644 index 9accf8ccd..000000000 --- a/src/backends/native/meta-kms-connector-private.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_CONNECTOR_PRIVATE_H -#define META_KMS_CONNECTOR_PRIVATE_H - -#include "backends/native/meta-kms-connector.h" - -typedef enum _MetaKmsConnectorProp -{ - META_KMS_CONNECTOR_PROP_CRTC_ID = 0, - META_KMS_CONNECTOR_PROP_DPMS, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER, - META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER, - META_KMS_CONNECTOR_N_PROPS -} MetaKmsConnectorProp; - -uint32_t meta_kms_connector_get_prop_id (MetaKmsConnector *connector, - MetaKmsConnectorProp prop); - -const char * meta_kms_connector_get_prop_name (MetaKmsConnector *connector, - MetaKmsConnectorProp prop); - -void meta_kms_connector_update_state (MetaKmsConnector *connector, - drmModeRes *drm_resources); - -void meta_kms_connector_predict_state (MetaKmsConnector *connector, - MetaKmsUpdate *update); - -MetaKmsConnector * meta_kms_connector_new (MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector, - drmModeRes *drm_resources); - -gboolean meta_kms_connector_is_same_as (MetaKmsConnector *connector, - drmModeConnector *drm_connector); - -#endif /* META_KMS_CONNECTOR_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c deleted file mode 100644 index a666bb45c..000000000 --- a/src/backends/native/meta-kms-connector.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-connector.h" -#include "backends/native/meta-kms-connector-private.h" - -#include <errno.h> - -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-impl-device.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-update-private.h" - -typedef struct _MetaKmsConnectorPropTable -{ - MetaKmsProp props[META_KMS_CONNECTOR_N_PROPS]; -} MetaKmsConnectorPropTable; - -struct _MetaKmsConnector -{ - GObject parent; - - MetaKmsDevice *device; - - uint32_t id; - uint32_t type; - uint32_t type_id; - char *name; - - MetaKmsConnectorState *current_state; - - MetaKmsConnectorPropTable prop_table; - - uint32_t edid_blob_id; - uint32_t tile_blob_id; - - gboolean fd_held; -}; - -G_DEFINE_TYPE (MetaKmsConnector, meta_kms_connector, G_TYPE_OBJECT) - -MetaKmsDevice * -meta_kms_connector_get_device (MetaKmsConnector *connector) -{ - return connector->device; -} - -uint32_t -meta_kms_connector_get_prop_id (MetaKmsConnector *connector, - MetaKmsConnectorProp prop) -{ - return connector->prop_table.props[prop].prop_id; -} - -const char * -meta_kms_connector_get_prop_name (MetaKmsConnector *connector, - MetaKmsConnectorProp prop) -{ - return connector->prop_table.props[prop].name; -} - -uint32_t -meta_kms_connector_get_connector_type (MetaKmsConnector *connector) -{ - return connector->type; -} - -uint32_t -meta_kms_connector_get_id (MetaKmsConnector *connector) -{ - return connector->id; -} - -const char * -meta_kms_connector_get_name (MetaKmsConnector *connector) -{ - return connector->name; -} - -gboolean -meta_kms_connector_can_clone (MetaKmsConnector *connector, - MetaKmsConnector *other_connector) -{ - MetaKmsConnectorState *state = connector->current_state; - MetaKmsConnectorState *other_state = other_connector->current_state; - - if (state->common_possible_clones == 0 || - other_state->common_possible_clones == 0) - return FALSE; - - if (state->encoder_device_idxs != other_state->encoder_device_idxs) - return FALSE; - - return TRUE; -} - -const MetaKmsConnectorState * -meta_kms_connector_get_current_state (MetaKmsConnector *connector) -{ - return connector->current_state; -} - -gboolean -meta_kms_connector_is_underscanning_supported (MetaKmsConnector *connector) -{ - uint32_t underscan_prop_id; - - underscan_prop_id = - connector->prop_table.props[META_KMS_CONNECTOR_PROP_UNDERSCAN].prop_id; - - return underscan_prop_id != 0; -} - -static void -sync_fd_held (MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device) -{ - gboolean should_hold_fd; - - should_hold_fd = connector->current_state->current_crtc_id != 0; - - if (connector->fd_held == should_hold_fd) - return; - - if (should_hold_fd) - meta_kms_impl_device_hold_fd (impl_device); - else - meta_kms_impl_device_unhold_fd (impl_device); - - connector->fd_held = should_hold_fd; -} - -static void -set_panel_orientation (MetaKmsConnectorState *state, - drmModePropertyPtr prop, - uint64_t orientation) -{ - const char *name; - - name = prop->enums[orientation].name; - if (strcmp (name, "Upside Down") == 0) - { - state->panel_orientation_transform = META_MONITOR_TRANSFORM_180; - } - else if (strcmp (name, "Left Side Up") == 0) - { - /* Left side up, rotate 90 degrees counter clockwise to correct */ - state->panel_orientation_transform = META_MONITOR_TRANSFORM_90; - } - else if (strcmp (name, "Right Side Up") == 0) - { - /* Right side up, rotate 270 degrees counter clockwise to correct */ - state->panel_orientation_transform = META_MONITOR_TRANSFORM_270; - } - else - { - state->panel_orientation_transform = META_MONITOR_TRANSFORM_NORMAL; - } -} - -static void -state_set_properties (MetaKmsConnectorState *state, - MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector) -{ - int fd; - int i; - - fd = meta_kms_impl_device_get_fd (impl_device); - - for (i = 0; i < drm_connector->count_props; i++) - { - drmModePropertyPtr prop; - - prop = drmModeGetProperty (fd, drm_connector->props[i]); - if (!prop) - continue; - - if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "suggested X") == 0) - state->suggested_x = drm_connector->prop_values[i]; - else if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "suggested Y") == 0) - state->suggested_y = drm_connector->prop_values[i]; - else if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "hotplug_mode_update") == 0) - state->hotplug_mode_update = drm_connector->prop_values[i]; - else if (strcmp (prop->name, "scaling mode") == 0) - state->has_scaling = TRUE; - else if ((prop->flags & DRM_MODE_PROP_ENUM) && - strcmp (prop->name, "panel orientation") == 0) - set_panel_orientation (state, prop, drm_connector->prop_values[i]); - else if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "non-desktop") == 0) - state->non_desktop = drm_connector->prop_values[i]; - - drmModeFreeProperty (prop); - } -} - -static CoglSubpixelOrder -drm_subpixel_order_to_cogl_subpixel_order (drmModeSubPixel subpixel) -{ - switch (subpixel) - { - case DRM_MODE_SUBPIXEL_NONE: - return COGL_SUBPIXEL_ORDER_NONE; - break; - case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB: - return COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB; - break; - case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR: - return COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR; - break; - case DRM_MODE_SUBPIXEL_VERTICAL_RGB: - return COGL_SUBPIXEL_ORDER_VERTICAL_RGB; - break; - case DRM_MODE_SUBPIXEL_VERTICAL_BGR: - return COGL_SUBPIXEL_ORDER_VERTICAL_BGR; - break; - case DRM_MODE_SUBPIXEL_UNKNOWN: - return COGL_SUBPIXEL_ORDER_UNKNOWN; - } - return COGL_SUBPIXEL_ORDER_UNKNOWN; -} - -static void -state_set_edid (MetaKmsConnectorState *state, - MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device, - uint32_t blob_id) -{ - int fd; - drmModePropertyBlobPtr edid_blob; - GBytes *edid_data; - - fd = meta_kms_impl_device_get_fd (impl_device); - edid_blob = drmModeGetPropertyBlob (fd, blob_id); - if (!edid_blob) - { - g_warning ("Failed to read EDID of connector %s: %s", - connector->name, g_strerror (errno)); - return; - } - - edid_data = g_bytes_new (edid_blob->data, edid_blob->length); - drmModeFreePropertyBlob (edid_blob); - - state->edid_data = edid_data; -} - -static void -state_set_tile_info (MetaKmsConnectorState *state, - MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device, - uint32_t blob_id) -{ - int fd; - drmModePropertyBlobPtr tile_blob; - - state->tile_info = (MetaTileInfo) { 0 }; - - fd = meta_kms_impl_device_get_fd (impl_device); - tile_blob = drmModeGetPropertyBlob (fd, blob_id); - if (!tile_blob) - { - g_warning ("Failed to read TILE of connector %s: %s", - connector->name, strerror (errno)); - return; - } - - if (tile_blob->length > 0) - { - if (sscanf ((char *) tile_blob->data, "%d:%d:%d:%d:%d:%d:%d:%d", - &state->tile_info.group_id, - &state->tile_info.flags, - &state->tile_info.max_h_tiles, - &state->tile_info.max_v_tiles, - &state->tile_info.loc_h_tile, - &state->tile_info.loc_v_tile, - &state->tile_info.tile_w, - &state->tile_info.tile_h) != 8) - { - g_warning ("Couldn't understand TILE property blob of connector %s", - connector->name); - state->tile_info = (MetaTileInfo) { 0 }; - } - } - - drmModeFreePropertyBlob (tile_blob); -} - -static void -state_set_blobs (MetaKmsConnectorState *state, - MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector) -{ - int fd; - int i; - - fd = meta_kms_impl_device_get_fd (impl_device); - - for (i = 0; i < drm_connector->count_props; i++) - { - drmModePropertyPtr prop; - - prop = drmModeGetProperty (fd, drm_connector->props[i]); - if (!prop) - continue; - - if (prop->flags & DRM_MODE_PROP_BLOB) - { - uint32_t blob_id; - - blob_id = drm_connector->prop_values[i]; - - if (blob_id) - { - if (strcmp (prop->name, "EDID") == 0) - state_set_edid (state, connector, impl_device, blob_id); - else if (strcmp (prop->name, "TILE") == 0) - state_set_tile_info (state, connector, impl_device, blob_id); - } - } - - drmModeFreeProperty (prop); - } -} - -static void -state_set_physical_dimensions (MetaKmsConnectorState *state, - drmModeConnector *drm_connector) -{ - state->width_mm = drm_connector->mmWidth; - state->height_mm = drm_connector->mmHeight; -} - -static void -state_set_modes (MetaKmsConnectorState *state, - MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector) -{ - int i; - - for (i = 0; i < drm_connector->count_modes; i++) - { - MetaKmsMode *mode; - - mode = meta_kms_mode_new (impl_device, &drm_connector->modes[i], - META_KMS_MODE_FLAG_NONE); - state->modes = g_list_prepend (state->modes, mode); - } - state->modes = g_list_reverse (state->modes); -} - -static void -set_encoder_device_idx_bit (uint32_t *encoder_device_idxs, - uint32_t encoder_id, - MetaKmsImplDevice *impl_device, - drmModeRes *drm_resources) -{ - int fd; - int i; - - fd = meta_kms_impl_device_get_fd (impl_device); - - for (i = 0; i < drm_resources->count_encoders; i++) - { - drmModeEncoder *drm_encoder; - - drm_encoder = drmModeGetEncoder (fd, drm_resources->encoders[i]); - if (!drm_encoder) - continue; - - if (drm_encoder->encoder_id == encoder_id) - { - *encoder_device_idxs |= (1 << i); - drmModeFreeEncoder (drm_encoder); - break; - } - - drmModeFreeEncoder (drm_encoder); - } -} - -static void -state_set_crtc_state (MetaKmsConnectorState *state, - drmModeConnector *drm_connector, - MetaKmsImplDevice *impl_device, - drmModeRes *drm_resources) -{ - int fd; - int i; - uint32_t common_possible_crtcs; - uint32_t common_possible_clones; - uint32_t encoder_device_idxs; - - fd = meta_kms_impl_device_get_fd (impl_device); - - common_possible_crtcs = UINT32_MAX; - common_possible_clones = UINT32_MAX; - encoder_device_idxs = 0; - for (i = 0; i < drm_connector->count_encoders; i++) - { - drmModeEncoder *drm_encoder; - - drm_encoder = drmModeGetEncoder (fd, drm_connector->encoders[i]); - if (!drm_encoder) - continue; - - common_possible_crtcs &= drm_encoder->possible_crtcs; - common_possible_clones &= drm_encoder->possible_clones; - - set_encoder_device_idx_bit (&encoder_device_idxs, - drm_encoder->encoder_id, - impl_device, - drm_resources); - - if (drm_connector->encoder_id == drm_encoder->encoder_id) - state->current_crtc_id = drm_encoder->crtc_id; - - drmModeFreeEncoder (drm_encoder); - } - - state->common_possible_crtcs = common_possible_crtcs; - state->common_possible_clones = common_possible_clones; - state->encoder_device_idxs = encoder_device_idxs; -} - -static MetaKmsConnectorState * -meta_kms_connector_state_new (void) -{ - MetaKmsConnectorState *state; - - state = g_new0 (MetaKmsConnectorState, 1); - state->suggested_x = -1; - state->suggested_y = -1; - - return state; -} - -static void -meta_kms_connector_state_free (MetaKmsConnectorState *state) -{ - g_clear_pointer (&state->edid_data, g_bytes_unref); - g_list_free_full (state->modes, (GDestroyNotify) meta_kms_mode_free); - g_free (state); -} - -static void -meta_kms_connector_read_state (MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector, - drmModeRes *drm_resources) -{ - MetaKmsConnectorState *state; - - g_clear_pointer (&connector->current_state, meta_kms_connector_state_free); - - if (!drm_connector || drm_connector->connection != DRM_MODE_CONNECTED) - return; - - state = meta_kms_connector_state_new (); - - state_set_blobs (state, connector, impl_device, drm_connector); - - state_set_properties (state, impl_device, drm_connector); - - state->subpixel_order = - drm_subpixel_order_to_cogl_subpixel_order (drm_connector->subpixel); - - state_set_physical_dimensions (state, drm_connector); - - state_set_modes (state, impl_device, drm_connector); - - state_set_crtc_state (state, drm_connector, impl_device, drm_resources); - - connector->current_state = state; - - sync_fd_held (connector, impl_device); -} - -void -meta_kms_connector_update_state (MetaKmsConnector *connector, - drmModeRes *drm_resources) -{ - MetaKmsImplDevice *impl_device; - drmModeConnector *drm_connector; - - impl_device = meta_kms_device_get_impl_device (connector->device); - drm_connector = drmModeGetConnector (meta_kms_impl_device_get_fd (impl_device), - connector->id); - meta_kms_connector_read_state (connector, impl_device, - drm_connector, - drm_resources); - if (drm_connector) - drmModeFreeConnector (drm_connector); -} - -void -meta_kms_connector_predict_state (MetaKmsConnector *connector, - MetaKmsUpdate *update) -{ - MetaKmsImplDevice *impl_device; - MetaKmsConnectorState *current_state; - GList *mode_sets; - GList *l; - current_state = connector->current_state; - if (!current_state) - return; - - mode_sets = meta_kms_update_get_mode_sets (update); - for (l = mode_sets; l; l = l->next) - { - MetaKmsModeSet *mode_set = l->data; - MetaKmsCrtc *crtc = mode_set->crtc; - - if (current_state->current_crtc_id == meta_kms_crtc_get_id (crtc)) - { - if (g_list_find (mode_set->connectors, connector)) - break; - else - current_state->current_crtc_id = 0; - } - else - { - if (g_list_find (mode_set->connectors, connector)) - { - current_state->current_crtc_id = meta_kms_crtc_get_id (crtc); - break; - } - } - } - - impl_device = meta_kms_device_get_impl_device (connector->device); - sync_fd_held (connector, impl_device); -} - -static void -init_properties (MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector) -{ - MetaKmsConnectorPropTable *prop_table = &connector->prop_table; - - *prop_table = (MetaKmsConnectorPropTable) { - .props = { - [META_KMS_CONNECTOR_PROP_CRTC_ID] = - { - .name = "CRTC_ID", - .type = DRM_MODE_PROP_OBJECT, - }, - [META_KMS_CONNECTOR_PROP_DPMS] = - { - .name = "DPMS", - .type = DRM_MODE_PROP_ENUM, - }, - [META_KMS_CONNECTOR_PROP_UNDERSCAN] = - { - .name = "underscan", - .type = DRM_MODE_PROP_ENUM, - }, - [META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER] = - { - .name = "underscan hborder", - .type = DRM_MODE_PROP_RANGE, - }, - [META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER] = - { - .name = "underscan vborder", - .type = DRM_MODE_PROP_RANGE, - }, - } - }; - - meta_kms_impl_device_init_prop_table (impl_device, - drm_connector->props, - drm_connector->prop_values, - drm_connector->count_props, - connector->prop_table.props, - META_KMS_CONNECTOR_N_PROPS, - NULL); -} - -static char * -make_connector_name (drmModeConnector *drm_connector) -{ - static const char * const connector_type_names[] = { - "None", - "VGA", - "DVI-I", - "DVI-D", - "DVI-A", - "Composite", - "SVIDEO", - "LVDS", - "Component", - "DIN", - "DP", - "HDMI", - "HDMI-B", - "TV", - "eDP", - "Virtual", - "DSI", - }; - - if (drm_connector->connector_type < G_N_ELEMENTS (connector_type_names)) - return g_strdup_printf ("%s-%d", - connector_type_names[drm_connector->connector_type], - drm_connector->connector_type_id); - else - return g_strdup_printf ("Unknown%d-%d", - drm_connector->connector_type, - drm_connector->connector_type_id); -} - -gboolean -meta_kms_connector_is_same_as (MetaKmsConnector *connector, - drmModeConnector *drm_connector) -{ - return (connector->id == drm_connector->connector_id && - connector->type == drm_connector->connector_type && - connector->type_id == drm_connector->connector_type_id); -} - -MetaKmsConnector * -meta_kms_connector_new (MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector, - drmModeRes *drm_resources) -{ - MetaKmsConnector *connector; - - connector = g_object_new (META_TYPE_KMS_CONNECTOR, NULL); - connector->device = meta_kms_impl_device_get_device (impl_device); - connector->id = drm_connector->connector_id; - connector->type = drm_connector->connector_type; - connector->type_id = drm_connector->connector_type_id; - connector->name = make_connector_name (drm_connector); - - init_properties (connector, impl_device, drm_connector); - - meta_kms_connector_read_state (connector, impl_device, - drm_connector, - drm_resources); - - return connector; -} - -static void -meta_kms_connector_finalize (GObject *object) -{ - MetaKmsConnector *connector = META_KMS_CONNECTOR (object); - - if (connector->fd_held) - { - MetaKmsImplDevice *impl_device; - - impl_device = meta_kms_device_get_impl_device (connector->device); - meta_kms_impl_device_unhold_fd (impl_device); - } - - g_clear_pointer (&connector->current_state, meta_kms_connector_state_free); - g_free (connector->name); - - G_OBJECT_CLASS (meta_kms_connector_parent_class)->finalize (object); -} - -static void -meta_kms_connector_init (MetaKmsConnector *connector) -{ -} - -static void -meta_kms_connector_class_init (MetaKmsConnectorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_kms_connector_finalize; -} diff --git a/src/backends/native/meta-kms-connector.h b/src/backends/native/meta-kms-connector.h deleted file mode 100644 index a3a7136c5..000000000 --- a/src/backends/native/meta-kms-connector.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_CONNECTOR_H -#define META_KMS_CONNECTOR_H - -#include <glib-object.h> -#include <stdint.h> -#include <xf86drmMode.h> - -#include "backends/meta-output.h" -#include "backends/native/meta-kms-types.h" - -#define META_TYPE_KMS_CONNECTOR (meta_kms_connector_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsConnector, meta_kms_connector, - META, KMS_CONNECTOR, GObject) - -typedef struct _MetaKmsConnectorState -{ - uint32_t current_crtc_id; - - uint32_t common_possible_crtcs; - uint32_t common_possible_clones; - uint32_t encoder_device_idxs; - - GList *modes; - - uint32_t width_mm; - uint32_t height_mm; - - MetaTileInfo tile_info; - GBytes *edid_data; - - gboolean has_scaling; - gboolean non_desktop; - - CoglSubpixelOrder subpixel_order; - - int suggested_x; - int suggested_y; - gboolean hotplug_mode_update; - - MetaMonitorTransform panel_orientation_transform; -} MetaKmsConnectorState; - -MetaKmsDevice * meta_kms_connector_get_device (MetaKmsConnector *connector); - -uint32_t meta_kms_connector_get_connector_type (MetaKmsConnector *connector); - -uint32_t meta_kms_connector_get_id (MetaKmsConnector *connector); - -const char * meta_kms_connector_get_name (MetaKmsConnector *connector); - -gboolean meta_kms_connector_can_clone (MetaKmsConnector *connector, - MetaKmsConnector *other_connector); - -const MetaKmsConnectorState * meta_kms_connector_get_current_state (MetaKmsConnector *connector); - -gboolean meta_kms_connector_is_underscanning_supported (MetaKmsConnector *connector); - -#endif /* META_KMS_CONNECTOR_H */ diff --git a/src/backends/native/meta-kms-crtc-private.h b/src/backends/native/meta-kms-crtc-private.h deleted file mode 100644 index 60c5fd309..000000000 --- a/src/backends/native/meta-kms-crtc-private.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_CRTC_PRIVATE_H -#define META_KMS_CRTC_PRIVATE_H - -#include <xf86drmMode.h> - -#include "backends/native/meta-kms-crtc.h" - -typedef enum _MetaKmsCrtcProp -{ - META_KMS_CRTC_PROP_MODE_ID = 0, - META_KMS_CRTC_PROP_ACTIVE, - META_KMS_CRTC_PROP_GAMMA_LUT, - META_KMS_CRTC_N_PROPS -} MetaKmsCrtcProp; - -MetaKmsCrtc * meta_kms_crtc_new (MetaKmsImplDevice *impl_device, - drmModeCrtc *drm_crtc, - int idx, - GError **error); - -void meta_kms_crtc_update_state (MetaKmsCrtc *crtc); - -void meta_kms_crtc_predict_state (MetaKmsCrtc *crtc, - MetaKmsUpdate *update); - -uint32_t meta_kms_crtc_get_prop_id (MetaKmsCrtc *crtc, - MetaKmsCrtcProp prop); - -const char * meta_kms_crtc_get_prop_name (MetaKmsCrtc *crtc, - MetaKmsCrtcProp prop); - -#endif /* META_KMS_CRTC_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c deleted file mode 100644 index 51d040b44..000000000 --- a/src/backends/native/meta-kms-crtc.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-crtc-private.h" - -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-impl-device.h" -#include "backends/native/meta-kms-mode.h" -#include "backends/native/meta-kms-update-private.h" - -typedef struct _MetaKmsCrtcPropTable -{ - MetaKmsProp props[META_KMS_CRTC_N_PROPS]; -} MetaKmsCrtcPropTable; - -struct _MetaKmsCrtc -{ - GObject parent; - - MetaKmsDevice *device; - - uint32_t id; - int idx; - - MetaKmsCrtcState current_state; - - MetaKmsCrtcPropTable prop_table; -}; - -G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT) - -MetaKmsDevice * -meta_kms_crtc_get_device (MetaKmsCrtc *crtc) -{ - return crtc->device; -} - -const MetaKmsCrtcState * -meta_kms_crtc_get_current_state (MetaKmsCrtc *crtc) -{ - return &crtc->current_state; -} - -uint32_t -meta_kms_crtc_get_id (MetaKmsCrtc *crtc) -{ - return crtc->id; -} - -int -meta_kms_crtc_get_idx (MetaKmsCrtc *crtc) -{ - return crtc->idx; -} - -uint32_t -meta_kms_crtc_get_prop_id (MetaKmsCrtc *crtc, - MetaKmsCrtcProp prop) -{ - return crtc->prop_table.props[prop].prop_id; -} - -const char * -meta_kms_crtc_get_prop_name (MetaKmsCrtc *crtc, - MetaKmsCrtcProp prop) -{ - return crtc->prop_table.props[prop].name; -} - -gboolean -meta_kms_crtc_is_active (MetaKmsCrtc *crtc) -{ - return crtc->current_state.is_active; -} - -static void -read_gamma_state (MetaKmsCrtc *crtc, - MetaKmsImplDevice *impl_device, - drmModeCrtc *drm_crtc) -{ - MetaKmsCrtcState *current_state = &crtc->current_state; - - if (current_state->gamma.size != drm_crtc->gamma_size) - { - current_state->gamma.size = drm_crtc->gamma_size; - - current_state->gamma.red = g_realloc_n (current_state->gamma.red, - drm_crtc->gamma_size, - sizeof (uint16_t)); - current_state->gamma.green = g_realloc_n (current_state->gamma.green, - drm_crtc->gamma_size, - sizeof (uint16_t)); - current_state->gamma.blue = g_realloc_n (current_state->gamma.blue, - drm_crtc->gamma_size, - sizeof (uint16_t)); - } - - drmModeCrtcGetGamma (meta_kms_impl_device_get_fd (impl_device), - crtc->id, - current_state->gamma.size, - current_state->gamma.red, - current_state->gamma.green, - current_state->gamma.blue); -} - -static int -find_prop_idx (MetaKmsProp *prop, - uint32_t *drm_props, - int n_drm_props) -{ - int i; - - g_return_val_if_fail (prop->prop_id > 0, -1); - - for (i = 0; i < n_drm_props; i++) - { - if (drm_props[i] == prop->prop_id) - return i; - } - - return -1; -} - -static void -meta_kms_crtc_read_state (MetaKmsCrtc *crtc, - MetaKmsImplDevice *impl_device, - drmModeCrtc *drm_crtc, - drmModeObjectProperties *drm_props) -{ - MetaKmsProp *active_prop; - int active_idx; - - crtc->current_state.rect = (MetaRectangle) { - .x = drm_crtc->x, - .y = drm_crtc->y, - .width = drm_crtc->width, - .height = drm_crtc->height, - }; - - crtc->current_state.is_drm_mode_valid = drm_crtc->mode_valid; - crtc->current_state.drm_mode = drm_crtc->mode; - - active_prop = &crtc->prop_table.props[META_KMS_CRTC_PROP_ACTIVE]; - if (active_prop->prop_id) - { - active_idx = find_prop_idx (active_prop, - drm_props->props, - drm_props->count_props); - crtc->current_state.is_active = !!drm_props->prop_values[active_idx]; - } - else - { - crtc->current_state.is_active = drm_crtc->mode_valid; - } - - meta_topic (META_DEBUG_KMS, - "Read CRTC %u state: active: %d, mode: %s", - crtc->id, crtc->current_state.is_active, - crtc->current_state.is_drm_mode_valid - ? crtc->current_state.drm_mode.name - : "(nil)"); - - read_gamma_state (crtc, impl_device, drm_crtc); -} - -void -meta_kms_crtc_update_state (MetaKmsCrtc *crtc) -{ - MetaKmsImplDevice *impl_device; - int fd; - drmModeCrtc *drm_crtc; - drmModeObjectProperties *drm_props; - - impl_device = meta_kms_device_get_impl_device (crtc->device); - fd = meta_kms_impl_device_get_fd (impl_device); - - drm_crtc = drmModeGetCrtc (fd, crtc->id); - drm_props = drmModeObjectGetProperties (fd, crtc->id, DRM_MODE_OBJECT_CRTC); - - if (!drm_crtc || !drm_props) - { - crtc->current_state.is_active = FALSE; - crtc->current_state.rect = (MetaRectangle) { }; - crtc->current_state.is_drm_mode_valid = FALSE; - goto out; - } - - meta_kms_crtc_read_state (crtc, impl_device, drm_crtc, drm_props); - -out: - g_clear_pointer (&drm_props, drmModeFreeObjectProperties); - g_clear_pointer (&drm_crtc, drmModeFreeCrtc); -} - -static void -clear_gamma_state (MetaKmsCrtc *crtc) -{ - crtc->current_state.gamma.size = 0; - g_clear_pointer (&crtc->current_state.gamma.red, g_free); - g_clear_pointer (&crtc->current_state.gamma.green, g_free); - g_clear_pointer (&crtc->current_state.gamma.blue, g_free); -} - -void -meta_kms_crtc_predict_state (MetaKmsCrtc *crtc, - MetaKmsUpdate *update) -{ - GList *mode_sets; - GList *crtc_gammas; - GList *l; - - mode_sets = meta_kms_update_get_mode_sets (update); - for (l = mode_sets; l; l = l->next) - { - MetaKmsModeSet *mode_set = l->data; - - if (mode_set->crtc != crtc) - continue; - - if (mode_set->mode) - { - MetaKmsPlaneAssignment *plane_assignment; - const drmModeModeInfo *drm_mode; - - plane_assignment = - meta_kms_update_get_primary_plane_assignment (update, crtc); - drm_mode = meta_kms_mode_get_drm_mode (mode_set->mode); - - crtc->current_state.is_active = TRUE; - crtc->current_state.rect = - meta_fixed_16_rectangle_to_rectangle (plane_assignment->src_rect); - crtc->current_state.is_drm_mode_valid = TRUE; - crtc->current_state.drm_mode = *drm_mode; - } - else - { - crtc->current_state.is_active = FALSE; - crtc->current_state.rect = (MetaRectangle) { 0 }; - crtc->current_state.is_drm_mode_valid = FALSE; - crtc->current_state.drm_mode = (drmModeModeInfo) { 0 }; - } - - break; - } - - crtc_gammas = meta_kms_update_get_crtc_gammas (update); - for (l = crtc_gammas; l; l = l->next) - { - MetaKmsCrtcGamma *gamma = l->data; - - if (gamma->crtc != crtc) - continue; - - clear_gamma_state (crtc); - crtc->current_state.gamma.size = gamma->size; - crtc->current_state.gamma.red = - g_memdup2 (gamma->red, gamma->size * sizeof (uint16_t)); - crtc->current_state.gamma.green = - g_memdup2 (gamma->green, gamma->size * sizeof (uint16_t)); - crtc->current_state.gamma.blue = - g_memdup2 (gamma->blue, gamma->size * sizeof (uint16_t)); - - break; - } -} - -static void -parse_active (MetaKmsImplDevice *impl_device, - MetaKmsProp *prop, - drmModePropertyPtr drm_prop, - uint64_t drm_prop_value, - gpointer user_data) -{ - MetaKmsCrtc *crtc = user_data; - - crtc->current_state.is_active = !!drm_prop_value; -} - -static void -init_proporties (MetaKmsCrtc *crtc, - MetaKmsImplDevice *impl_device, - drmModeCrtc *drm_crtc) -{ - MetaKmsCrtcPropTable *prop_table = &crtc->prop_table; - int fd; - drmModeObjectProperties *drm_props; - - *prop_table = (MetaKmsCrtcPropTable) { - .props = { - [META_KMS_CRTC_PROP_MODE_ID] = - { - .name = "MODE_ID", - .type = DRM_MODE_PROP_BLOB, - }, - [META_KMS_CRTC_PROP_ACTIVE] = - { - .name = "ACTIVE", - .type = DRM_MODE_PROP_RANGE, - .parse = parse_active, - }, - [META_KMS_CRTC_PROP_GAMMA_LUT] = - { - .name = "GAMMA_LUT", - .type = DRM_MODE_PROP_BLOB, - }, - } - }; - - fd = meta_kms_impl_device_get_fd (impl_device); - drm_props = drmModeObjectGetProperties (fd, - drm_crtc->crtc_id, - DRM_MODE_OBJECT_CRTC); - - meta_kms_impl_device_init_prop_table (impl_device, - drm_props->props, - drm_props->prop_values, - drm_props->count_props, - crtc->prop_table.props, - META_KMS_CRTC_N_PROPS, - crtc); - - drmModeFreeObjectProperties (drm_props); -} - -MetaKmsCrtc * -meta_kms_crtc_new (MetaKmsImplDevice *impl_device, - drmModeCrtc *drm_crtc, - int idx, - GError **error) -{ - int fd; - drmModeObjectProperties *drm_props; - MetaKmsCrtc *crtc; - - fd = meta_kms_impl_device_get_fd (impl_device); - drm_props = drmModeObjectGetProperties (fd, drm_crtc->crtc_id, - DRM_MODE_OBJECT_CRTC); - if (!drm_props) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "drmModeObjectGetProperties: %s", g_strerror (errno)); - return NULL; - } - - crtc = g_object_new (META_TYPE_KMS_CRTC, NULL); - crtc->device = meta_kms_impl_device_get_device (impl_device); - crtc->id = drm_crtc->crtc_id; - crtc->idx = idx; - - init_proporties (crtc, impl_device, drm_crtc); - - meta_kms_crtc_read_state (crtc, impl_device, drm_crtc, drm_props); - - drmModeFreeObjectProperties (drm_props); - - return crtc; -} - -static void -meta_kms_crtc_finalize (GObject *object) -{ - MetaKmsCrtc *crtc = META_KMS_CRTC (object); - - clear_gamma_state (crtc); - - G_OBJECT_CLASS (meta_kms_crtc_parent_class)->finalize (object); -} - -static void -meta_kms_crtc_init (MetaKmsCrtc *crtc) -{ -} - -static void -meta_kms_crtc_class_init (MetaKmsCrtcClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_kms_crtc_finalize; -} diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h deleted file mode 100644 index 406ca3ac1..000000000 --- a/src/backends/native/meta-kms-crtc.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_CRTC_H -#define META_KMS_CRTC_H - -#include <glib-object.h> -#include <stdint.h> -#include <xf86drmMode.h> - -#include "backends/native/meta-kms-types.h" -#include "meta/boxes.h" - -typedef struct _MetaKmsCrtcState -{ - gboolean is_active; - - MetaRectangle rect; - gboolean is_drm_mode_valid; - drmModeModeInfo drm_mode; - - struct { - uint16_t *red; - uint16_t *green; - uint16_t *blue; - - int size; - } gamma; -} MetaKmsCrtcState; - -typedef struct _MetaKmsCrtcGamma -{ - MetaKmsCrtc *crtc; - int size; - uint16_t *red; - uint16_t *green; - uint16_t *blue; -} MetaKmsCrtcGamma; - -#define META_TYPE_KMS_CRTC (meta_kms_crtc_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsCrtc, meta_kms_crtc, - META, KMS_CRTC, - GObject) - -MetaKmsDevice * meta_kms_crtc_get_device (MetaKmsCrtc *crtc); - -const MetaKmsCrtcState * meta_kms_crtc_get_current_state (MetaKmsCrtc *crtc); - -uint32_t meta_kms_crtc_get_id (MetaKmsCrtc *crtc); - -int meta_kms_crtc_get_idx (MetaKmsCrtc *crtc); - -gboolean meta_kms_crtc_is_active (MetaKmsCrtc *crtc); - -void meta_kms_crtc_gamma_free (MetaKmsCrtcGamma *gamma); - -MetaKmsCrtcGamma * meta_kms_crtc_gamma_new (MetaKmsCrtc *crtc, - int size, - const uint16_t *red, - const uint16_t *green, - const uint16_t *blue); - -#endif /* META_KMS_CRTC_H */ diff --git a/src/backends/native/meta-kms-device-private.h b/src/backends/native/meta-kms-device-private.h deleted file mode 100644 index 41e05a2f7..000000000 --- a/src/backends/native/meta-kms-device-private.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_DEVICE_PRIVATE_H -#define META_KMS_DEVICE_PRIVATE_H - -#include "backends/native/meta-kms-types.h" - -MetaKmsImplDevice * meta_kms_device_get_impl_device (MetaKmsDevice *device); - -void meta_kms_device_update_states_in_impl (MetaKmsDevice *device); - -void meta_kms_device_predict_states_in_impl (MetaKmsDevice *device, - MetaKmsUpdate *update); - -void meta_kms_device_add_fake_plane_in_impl (MetaKmsDevice *device, - MetaKmsPlaneType plane_type, - MetaKmsCrtc *crtc); - -#endif /* META_KMS_DEVICE_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c deleted file mode 100644 index b4d3e5802..000000000 --- a/src/backends/native/meta-kms-device.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat - * Copyright (C) 2019 DisplayLink (UK) Ltd. - * - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-device.h" - -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <xf86drm.h> - -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-kms-impl-device-atomic.h" -#include "backends/native/meta-kms-impl-device-dummy.h" -#include "backends/native/meta-kms-impl-device-simple.h" -#include "backends/native/meta-kms-impl-device.h" -#include "backends/native/meta-kms-impl.h" -#include "backends/native/meta-kms-plane.h" -#include "backends/native/meta-kms-private.h" - -struct _MetaKmsDevice -{ - GObject parent; - - MetaKms *kms; - - MetaKmsImplDevice *impl_device; - - MetaKmsDeviceFlag flags; - char *path; - char *driver_name; - char *driver_description; - - GList *crtcs; - GList *connectors; - GList *planes; - - MetaKmsDeviceCaps caps; - - GList *fallback_modes; -}; - -G_DEFINE_TYPE (MetaKmsDevice, meta_kms_device, G_TYPE_OBJECT); - -MetaKms * -meta_kms_device_get_kms (MetaKmsDevice *device) -{ - return device->kms; -} - -MetaKmsImplDevice * -meta_kms_device_get_impl_device (MetaKmsDevice *device) -{ - return device->impl_device; -} - -const char * -meta_kms_device_get_path (MetaKmsDevice *device) -{ - return device->path; -} - -const char * -meta_kms_device_get_driver_name (MetaKmsDevice *device) -{ - return device->driver_name; -} - -const char * -meta_kms_device_get_driver_description (MetaKmsDevice *device) -{ - return device->driver_description; -} - -MetaKmsDeviceFlag -meta_kms_device_get_flags (MetaKmsDevice *device) -{ - return device->flags; -} - -gboolean -meta_kms_device_get_cursor_size (MetaKmsDevice *device, - uint64_t *out_cursor_width, - uint64_t *out_cursor_height) -{ - if (device->caps.has_cursor_size) - { - *out_cursor_width = device->caps.cursor_width; - *out_cursor_height = device->caps.cursor_height; - return TRUE; - } - else - { - return FALSE; - } -} - -gboolean -meta_kms_device_prefers_shadow_buffer (MetaKmsDevice *device) -{ - return device->caps.prefers_shadow_buffer; -} - -gboolean -meta_kms_device_uses_monotonic_clock (MetaKmsDevice *device) -{ - return device->caps.uses_monotonic_clock; -} - -GList * -meta_kms_device_get_connectors (MetaKmsDevice *device) -{ - return device->connectors; -} - -GList * -meta_kms_device_get_crtcs (MetaKmsDevice *device) -{ - return device->crtcs; -} - -GList * -meta_kms_device_get_planes (MetaKmsDevice *device) -{ - return device->planes; -} - -static MetaKmsPlane * -get_plane_with_type_for (MetaKmsDevice *device, - MetaKmsCrtc *crtc, - MetaKmsPlaneType type) -{ - GList *l; - - for (l = meta_kms_device_get_planes (device); l; l = l->next) - { - MetaKmsPlane *plane = l->data; - - if (meta_kms_plane_get_plane_type (plane) != type) - continue; - - if (meta_kms_plane_is_usable_with (plane, crtc)) - return plane; - } - - return NULL; -} - -MetaKmsPlane * -meta_kms_device_get_primary_plane_for (MetaKmsDevice *device, - MetaKmsCrtc *crtc) -{ - return get_plane_with_type_for (device, crtc, META_KMS_PLANE_TYPE_PRIMARY); -} - -MetaKmsPlane * -meta_kms_device_get_cursor_plane_for (MetaKmsDevice *device, - MetaKmsCrtc *crtc) -{ - return get_plane_with_type_for (device, crtc, META_KMS_PLANE_TYPE_CURSOR); -} - -GList * -meta_kms_device_get_fallback_modes (MetaKmsDevice *device) -{ - return device->fallback_modes; -} - -void -meta_kms_device_update_states_in_impl (MetaKmsDevice *device) -{ - MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); - - meta_assert_in_kms_impl (device->kms); - meta_assert_is_waiting_for_kms_impl_task (device->kms); - - meta_kms_impl_device_update_states (impl_device); - - g_list_free (device->crtcs); - device->crtcs = meta_kms_impl_device_copy_crtcs (impl_device); - - g_list_free (device->connectors); - device->connectors = meta_kms_impl_device_copy_connectors (impl_device); - - g_list_free (device->planes); - device->planes = meta_kms_impl_device_copy_planes (impl_device); -} - -void -meta_kms_device_predict_states_in_impl (MetaKmsDevice *device, - MetaKmsUpdate *update) -{ - MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); - - meta_assert_in_kms_impl (device->kms); - - meta_kms_impl_device_predict_states (impl_device, update); -} - -void -meta_kms_device_add_fake_plane_in_impl (MetaKmsDevice *device, - MetaKmsPlaneType plane_type, - MetaKmsCrtc *crtc) -{ - MetaKmsImplDevice *impl_device = device->impl_device; - MetaKmsPlane *plane; - - meta_assert_in_kms_impl (device->kms); - - plane = meta_kms_impl_device_add_fake_plane (impl_device, - plane_type, - crtc); - device->planes = g_list_append (device->planes, plane); -} - -typedef struct _CreateImplDeviceData -{ - MetaKmsDevice *device; - const char *path; - MetaKmsDeviceFlag flags; - - MetaKmsImplDevice *out_impl_device; - GList *out_crtcs; - GList *out_connectors; - GList *out_planes; - MetaKmsDeviceCaps out_caps; - GList *out_fallback_modes; - char *out_driver_name; - char *out_driver_description; - char *out_path; -} CreateImplDeviceData; - -static const char * -impl_device_type_to_string (GType type) -{ - if (type == META_TYPE_KMS_IMPL_DEVICE_ATOMIC) - return "atomic modesetting"; - else if (type == META_TYPE_KMS_IMPL_DEVICE_SIMPLE) - return "legacy modesetting"; - else if (type == META_TYPE_KMS_IMPL_DEVICE_DUMMY) - return "no modesetting"; - g_assert_not_reached(); -} - -static MetaKmsImplDevice * -meta_create_kms_impl_device (MetaKmsDevice *device, - MetaKmsImpl *impl, - const char *path, - MetaKmsDeviceFlag flags, - GError **error) -{ - meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl)); - - if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING) - { - return g_initable_new (META_TYPE_KMS_IMPL_DEVICE_DUMMY, - NULL, error, - "device", device, - "impl", impl, - "path", path, - "flags", flags, - NULL); - } - else - { - GType impl_device_types[] = { - META_TYPE_KMS_IMPL_DEVICE_ATOMIC, - META_TYPE_KMS_IMPL_DEVICE_SIMPLE, - }; - int i; - - for (i = 0; i < G_N_ELEMENTS (impl_device_types); i++) - { - MetaKmsImplDevice *impl_device; - g_autoptr (GError) local_error = NULL; - - impl_device = g_initable_new (impl_device_types[i], - NULL, &local_error, - "device", device, - "impl", impl, - "path", path, - "flags", flags, - NULL); - if (impl_device) - return impl_device; - - if (local_error->domain != META_KMS_ERROR) - { - g_warning ("Failed to open %s backend: %s", - impl_device_type_to_string (impl_device_types[i]), - local_error->message); - } - } - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No suitable mode setting backend found"); - - return NULL; - } -} - -static gpointer -create_impl_device_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - CreateImplDeviceData *data = user_data; - MetaKmsImplDevice *impl_device; - - impl_device = meta_create_kms_impl_device (data->device, - impl, - data->path, - data->flags, - error); - if (!impl_device) - return FALSE; - - meta_kms_impl_add_impl_device (impl, impl_device); - - data->out_impl_device = impl_device; - data->out_crtcs = meta_kms_impl_device_copy_crtcs (impl_device); - data->out_connectors = meta_kms_impl_device_copy_connectors (impl_device); - data->out_planes = meta_kms_impl_device_copy_planes (impl_device); - data->out_caps = *meta_kms_impl_device_get_caps (impl_device); - data->out_fallback_modes = - meta_kms_impl_device_copy_fallback_modes (impl_device); - data->out_driver_name = - g_strdup (meta_kms_impl_device_get_driver_name (impl_device)); - data->out_driver_description = - g_strdup (meta_kms_impl_device_get_driver_description (impl_device)); - data->out_path = g_strdup (meta_kms_impl_device_get_path (impl_device)); - - return GINT_TO_POINTER (TRUE); -} - -MetaKmsDevice * -meta_kms_device_new (MetaKms *kms, - const char *path, - MetaKmsDeviceFlag flags, - GError **error) -{ - MetaKmsDevice *device; - CreateImplDeviceData data; - - device = g_object_new (META_TYPE_KMS_DEVICE, NULL); - device->kms = kms; - - data = (CreateImplDeviceData) { - .device = device, - .path = path, - .flags = flags, - }; - if (!meta_kms_run_impl_task_sync (kms, create_impl_device_in_impl, &data, - error)) - { - g_object_unref (device); - return NULL; - } - - device->impl_device = data.out_impl_device; - device->flags = flags; - device->path = g_strdup (path); - device->crtcs = data.out_crtcs; - device->connectors = data.out_connectors; - device->planes = data.out_planes; - device->caps = data.out_caps; - device->fallback_modes = data.out_fallback_modes; - device->driver_name = data.out_driver_name; - device->driver_description = data.out_driver_description; - free (device->path); - device->path = data.out_path; - - return device; -} - -static gpointer -free_impl_device_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - MetaKmsImplDevice *impl_device = user_data; - - g_object_unref (impl_device); - - return GINT_TO_POINTER (TRUE); -} - -static void -meta_kms_device_finalize (GObject *object) -{ - MetaKmsDevice *device = META_KMS_DEVICE (object); - - g_free (device->path); - g_list_free (device->crtcs); - g_list_free (device->connectors); - g_list_free (device->planes); - - if (device->impl_device) - { - meta_kms_run_impl_task_sync (device->kms, free_impl_device_in_impl, - device->impl_device, - NULL); - } - - G_OBJECT_CLASS (meta_kms_device_parent_class)->finalize (object); -} - -static void -meta_kms_device_init (MetaKmsDevice *device) -{ -} - -static void -meta_kms_device_class_init (MetaKmsDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_kms_device_finalize; -} diff --git a/src/backends/native/meta-kms-device.h b/src/backends/native/meta-kms-device.h deleted file mode 100644 index 58dda6136..000000000 --- a/src/backends/native/meta-kms-device.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_DEVICE_H -#define META_KMS_DEVICE_H - -#include <glib-object.h> - -#include "backends/native/meta-kms-types.h" - -#define META_TYPE_KMS_DEVICE (meta_kms_device_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsDevice, meta_kms_device, - META, KMS_DEVICE, - GObject) - -MetaKms * meta_kms_device_get_kms (MetaKmsDevice *device); - -const char * meta_kms_device_get_path (MetaKmsDevice *device); - -const char * meta_kms_device_get_driver_name (MetaKmsDevice *device); - -const char * meta_kms_device_get_driver_description (MetaKmsDevice *device); - -MetaKmsDeviceFlag meta_kms_device_get_flags (MetaKmsDevice *device); - -gboolean meta_kms_device_get_cursor_size (MetaKmsDevice *device, - uint64_t *out_cursor_width, - uint64_t *out_cursor_height); - -gboolean meta_kms_device_prefers_shadow_buffer (MetaKmsDevice *device); - -gboolean meta_kms_device_uses_monotonic_clock (MetaKmsDevice *device); - -GList * meta_kms_device_get_connectors (MetaKmsDevice *device); - -GList * meta_kms_device_get_crtcs (MetaKmsDevice *device); - -GList * meta_kms_device_get_planes (MetaKmsDevice *device); - -MetaKmsPlane * meta_kms_device_get_primary_plane_for (MetaKmsDevice *device, - MetaKmsCrtc *crtc); - -MetaKmsPlane * meta_kms_device_get_cursor_plane_for (MetaKmsDevice *device, - MetaKmsCrtc *crtc); - -GList * meta_kms_device_get_fallback_modes (MetaKmsDevice *device); - -MetaKmsDevice * meta_kms_device_new (MetaKms *kms, - const char *path, - MetaKmsDeviceFlag flags, - GError **error); - -#endif /* META_KMS_DEVICE_H */ diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c deleted file mode 100644 index 8e41207ee..000000000 --- a/src/backends/native/meta-kms-impl-device-atomic.c +++ /dev/null @@ -1,1202 +0,0 @@ -/* - * Copyright (C) 2019-2020 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-impl-device-atomic.h" - -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-kms-connector-private.h" -#include "backends/native/meta-kms-crtc-private.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-plane-private.h" -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-update-private.h" - -typedef gboolean (* MetaKmsAtomicProcessFunc) (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer entry_data, - gpointer user_data, - GError **error); - -struct _MetaKmsImplDeviceAtomic -{ - MetaKmsImplDevice parent; - - GHashTable *page_flip_datas; -}; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceAtomic, meta_kms_impl_device_atomic, - META_TYPE_KMS_IMPL_DEVICE, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static uint32_t -store_new_blob (MetaKmsImplDevice *impl_device, - GArray *blob_ids, - const void *data, - size_t size, - GError **error) -{ - int fd = meta_kms_impl_device_get_fd (impl_device); - uint32_t blob_id; - int ret; - - ret = drmModeCreatePropertyBlob (fd, data, size, &blob_id); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeCreatePropertyBlob: %s", g_strerror (-ret)); - return 0; - } - - g_array_append_val (blob_ids, blob_id); - - return blob_id; -} - -static void -release_blob_ids (MetaKmsImplDevice *impl_device, - GArray *blob_ids) -{ - int fd = meta_kms_impl_device_get_fd (impl_device); - unsigned int i; - - for (i = 0; i < blob_ids->len; i++) - { - uint32_t blob_id = g_array_index (blob_ids, uint32_t, i); - - drmModeDestroyPropertyBlob (fd, blob_id); - } -} - -static gboolean -add_connector_property (MetaKmsImplDevice *impl_device, - MetaKmsConnector *connector, - drmModeAtomicReq *req, - MetaKmsConnectorProp prop, - uint64_t value, - GError **error) -{ - int ret; - uint32_t prop_id; - - prop_id = meta_kms_connector_get_prop_id (connector, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Connector property '%s' not found", - meta_kms_connector_get_prop_name (connector, prop)); - return FALSE; - } - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting connector %u (%s) property '%s' (%u) to %" - G_GUINT64_FORMAT, - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device), - meta_kms_connector_get_prop_name (connector, prop), - meta_kms_connector_get_prop_id (connector, prop), - value); - ret = drmModeAtomicAddProperty (req, - meta_kms_connector_get_id (connector), - prop_id, - value); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicAddProperty, connector: %u, prop id: %u: %s", - meta_kms_connector_get_id (connector), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -process_connector_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsConnectorUpdate *connector_update = update_entry; - MetaKmsConnector *connector = connector_update->connector; - - if (connector_update->underscanning.has_update && - connector_update->underscanning.is_active) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Setting underscanning on connector %u (%s) to " - "%" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device), - connector_update->underscanning.hborder, - connector_update->underscanning.vborder); - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - 1, - error)) - return FALSE; - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER, - connector_update->underscanning.hborder, - error)) - return FALSE; - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER, - connector_update->underscanning.vborder, - error)) - return FALSE; - } - else if (connector_update->underscanning.has_update) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Unsetting underscanning on connector %u (%s)", - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device)); - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -add_crtc_property (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *crtc, - drmModeAtomicReq *req, - MetaKmsCrtcProp prop, - uint64_t value, - GError **error) -{ - int ret; - uint32_t prop_id; - - prop_id = meta_kms_crtc_get_prop_id (crtc, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "CRTC property (%s) not found", - meta_kms_crtc_get_prop_name (crtc, prop)); - return FALSE; - } - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting CRTC %u (%s) property '%s' (%u) to %" - G_GUINT64_FORMAT, - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - meta_kms_crtc_get_prop_name (crtc, prop), - meta_kms_crtc_get_prop_id (crtc, prop), - value); - ret = drmModeAtomicAddProperty (req, - meta_kms_crtc_get_id (crtc), - prop_id, - value); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicAddProperty, crtc: %u, prop: %s (%u): %s", - meta_kms_crtc_get_id (crtc), - meta_kms_crtc_get_prop_name (crtc, prop), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -process_mode_set (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsModeSet *mode_set = update_entry; - MetaKmsCrtc *crtc = mode_set->crtc; - MetaKmsMode *mode; - - mode = (MetaKmsMode *) mode_set->mode; - if (mode) - { - uint32_t mode_id; - GList *l; - - mode_id = meta_kms_mode_create_blob_id (mode, error); - if (mode_id == 0) - return FALSE; - - g_array_append_val (blob_ids, mode_id); - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting mode of CRTC %u (%s) to %s", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - meta_kms_mode_get_name (mode)); - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_MODE_ID, - mode_id, - error)) - return FALSE; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_ACTIVE, - 1, - error)) - return FALSE; - - for (l = mode_set->connectors; l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_CRTC_ID, - meta_kms_crtc_get_id (crtc), - error)) - return FALSE; - } - } - else - { - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_MODE_ID, - 0, - error)) - return FALSE; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_ACTIVE, - 0, - error)) - return FALSE; - - meta_topic (META_DEBUG_KMS, - "[atomic] Unsetting mode of (%u, %s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - } - - return TRUE; -} - -static gboolean -add_plane_property (MetaKmsImplDevice *impl_device, - MetaKmsPlane *plane, - drmModeAtomicReq *req, - MetaKmsCrtcProp prop, - uint64_t value, - GError **error) -{ - int ret; - uint32_t prop_id; - - prop_id = meta_kms_plane_get_prop_id (plane, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Plane property (%s) not found on %u", - meta_kms_plane_get_prop_name (plane, prop), - meta_kms_plane_get_id (plane)); - return FALSE; - } - - switch (meta_kms_plane_get_prop_internal_type (plane, prop)) - { - case META_KMS_PROP_TYPE_RAW: - meta_topic (META_DEBUG_KMS, - "[atomic] Setting plane %u (%s) property '%s' (%u) to %" - G_GUINT64_FORMAT, - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - meta_kms_plane_get_prop_name (plane, prop), - meta_kms_plane_get_prop_id (plane, prop), - value); - break; - case META_KMS_PROP_TYPE_FIXED_16: - meta_topic (META_DEBUG_KMS, - "[atomic] Setting plane %u (%s) property '%s' (%u) to %.2f", - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - meta_kms_plane_get_prop_name (plane, prop), - meta_kms_plane_get_prop_id (plane, prop), - meta_fixed_16_to_double (value)); - break; - } - ret = drmModeAtomicAddProperty (req, - meta_kms_plane_get_id (plane), - prop_id, - value); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicAddProperty, plane: %u, prop: %s (%u): %s", - meta_kms_plane_get_id (plane), - meta_kms_plane_get_prop_name (plane, prop), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static const char * -get_plane_type_string (MetaKmsPlane *plane) -{ - switch (meta_kms_plane_get_plane_type (plane)) - { - case META_KMS_PLANE_TYPE_PRIMARY: - return "primary"; - case META_KMS_PLANE_TYPE_CURSOR: - return "cursor"; - case META_KMS_PLANE_TYPE_OVERLAY: - return "overlay"; - } - - g_assert_not_reached (); -} - -static gboolean -process_plane_assignment (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsPlaneAssignment *plane_assignment = update_entry; - MetaKmsPlane *plane = plane_assignment->plane; - MetaDrmBuffer *buffer; - - buffer = plane_assignment->buffer; - - meta_topic (META_DEBUG_KMS, - "[atomic] Assigning %s plane (%u, %s) to %u, " - "%hdx%hd+%hd+%hd -> %dx%d+%d+%d", - get_plane_type_string (plane), - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - buffer ? meta_drm_buffer_get_fb_id (buffer) : 0, - meta_fixed_16_to_int (plane_assignment->src_rect.width), - meta_fixed_16_to_int (plane_assignment->src_rect.height), - meta_fixed_16_to_int (plane_assignment->src_rect.x), - meta_fixed_16_to_int (plane_assignment->src_rect.y), - plane_assignment->dst_rect.width, - plane_assignment->dst_rect.height, - plane_assignment->dst_rect.x, - plane_assignment->dst_rect.y); - - if (buffer) - { - int i; - struct { - MetaKmsPlaneProp prop; - uint64_t value; - } props[] = { - { - .prop = META_KMS_PLANE_PROP_FB_ID, - .value = meta_drm_buffer_get_fb_id (buffer), - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_ID, - .value = meta_kms_crtc_get_id (plane_assignment->crtc), - }, - { - .prop = META_KMS_PLANE_PROP_SRC_X, - .value = plane_assignment->src_rect.x, - }, - { - .prop = META_KMS_PLANE_PROP_SRC_Y, - .value = plane_assignment->src_rect.y, - }, - { - .prop = META_KMS_PLANE_PROP_SRC_W, - .value = plane_assignment->src_rect.width, - }, - { - .prop = META_KMS_PLANE_PROP_SRC_H, - .value = plane_assignment->src_rect.height, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_X, - .value = plane_assignment->dst_rect.x, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_Y, - .value = plane_assignment->dst_rect.y, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_W, - .value = plane_assignment->dst_rect.width, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_H, - .value = plane_assignment->dst_rect.height, - }, - }; - - for (i = 0; i < G_N_ELEMENTS (props); i++) - { - if (!add_plane_property (impl_device, - plane, req, - props[i].prop, - props[i].value, - error)) - return FALSE; - } - } - else - { - int i; - struct { - MetaKmsPlaneProp prop; - uint64_t value; - } props[] = { - { - .prop = META_KMS_PLANE_PROP_FB_ID, - .value = 0, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_ID, - .value = 0, - }, - }; - - for (i = 0; i < G_N_ELEMENTS (props); i++) - { - if (!add_plane_property (impl_device, - plane, req, - props[i].prop, - props[i].value, - error)) - return FALSE; - } - } - - if (plane_assignment->rotation) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Setting plane (%u, %s) rotation to %" - G_GUINT64_FORMAT, - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - plane_assignment->rotation); - - if (!add_plane_property (impl_device, - plane, req, - META_KMS_PLANE_PROP_ROTATION, - plane_assignment->rotation, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -process_crtc_gamma (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsCrtcGamma *gamma = update_entry; - MetaKmsCrtc *crtc = gamma->crtc; - struct drm_color_lut drm_color_lut[gamma->size]; - int i; - uint32_t color_lut_blob_id; - - for (i = 0; i < gamma->size; i++) - { - drm_color_lut[i].red = gamma->red[i]; - drm_color_lut[i].green = gamma->green[i]; - drm_color_lut[i].blue = gamma->blue[i]; - } - - color_lut_blob_id = store_new_blob (impl_device, - blob_ids, - drm_color_lut, - sizeof drm_color_lut, - error); - if (!color_lut_blob_id) - return FALSE; - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting CRTC (%u, %s) gamma, size: %d", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - gamma->size); - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_GAMMA_LUT, - color_lut_blob_id, - error)) - return FALSE; - - return TRUE; -} - -static gboolean -process_page_flip_listener (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = - META_KMS_IMPL_DEVICE_ATOMIC (impl_device); - MetaKmsPageFlipListener *listener = update_entry; - MetaKmsPageFlipData *page_flip_data; - uint32_t crtc_id; - gpointer listener_user_data; - GDestroyNotify listener_destroy_notify; - - crtc_id = meta_kms_crtc_get_id (listener->crtc); - page_flip_data = g_hash_table_lookup (impl_device_atomic->page_flip_datas, - GUINT_TO_POINTER (crtc_id)); - if (!page_flip_data) - { - page_flip_data = meta_kms_page_flip_data_new (impl_device, - listener->crtc); - g_hash_table_insert (impl_device_atomic->page_flip_datas, - GUINT_TO_POINTER (crtc_id), - page_flip_data); - - meta_kms_impl_device_hold_fd (impl_device); - - meta_topic (META_DEBUG_KMS, - "[atomic] Adding page flip data for (%u, %s): %p", - crtc_id, - meta_kms_impl_device_get_path (impl_device), - page_flip_data); - } - - listener_user_data = g_steal_pointer (&listener->user_data); - listener_destroy_notify = g_steal_pointer (&listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - listener->vtable, - listener->flags, - listener_user_data, - listener_destroy_notify); - - return TRUE; -} - -static gboolean -discard_page_flip_listener (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsPageFlipListener *listener = update_entry; - GError *commit_error = user_data; - MetaKmsPageFlipData *page_flip_data; - gpointer listener_user_data; - GDestroyNotify listener_destroy_notify; - - page_flip_data = meta_kms_page_flip_data_new (impl_device, - listener->crtc); - - meta_topic (META_DEBUG_KMS, - "[atomic] Creating transient page flip data for (%u, %s): %p", - meta_kms_crtc_get_id (listener->crtc), - meta_kms_impl_device_get_path (impl_device), - page_flip_data); - - listener_user_data = g_steal_pointer (&listener->user_data); - listener_destroy_notify = g_steal_pointer (&listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - listener->vtable, - listener->flags, - listener_user_data, - listener_destroy_notify); - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, commit_error); - - return TRUE; -} - -static gboolean -process_entries (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - GList *entries, - gpointer user_data, - MetaKmsAtomicProcessFunc func, - GError **error) -{ - GList *l; - - for (l = entries; l; l = l->next) - { - if (!func (impl_device, - update, - req, - blob_ids, - l->data, - user_data, - error)) - return FALSE; - } - - return TRUE; -} - -static void -atomic_page_flip_handler (int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - unsigned int crtc_id, - void *user_data) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = user_data; - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_atomic); - MetaKmsPageFlipData *page_flip_data = NULL; - - g_hash_table_steal_extended (impl_device_atomic->page_flip_datas, - GUINT_TO_POINTER (crtc_id), - NULL, - (gpointer *) &page_flip_data); - - meta_topic (META_DEBUG_KMS, - "[atomic] Page flip callback for CRTC (%u, %s), data: %p", - crtc_id, meta_kms_impl_device_get_path (impl_device), - page_flip_data); - - if (!page_flip_data) - return; - - meta_kms_impl_device_unhold_fd (impl_device); - - meta_kms_page_flip_data_set_timings_in_impl (page_flip_data, - sequence, tv_sec, tv_usec); - meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data); -} - -static void -meta_kms_impl_device_atomic_setup_drm_event_context (MetaKmsImplDevice *impl_device, - drmEventContext *drm_event_context) -{ - drm_event_context->version = 3; - drm_event_context->page_flip_handler2 = atomic_page_flip_handler; -} - -static const char * -commit_flags_string (uint32_t commit_flags) -{ - static char static_commit_flags_string[255]; - const char *commit_flag_strings[4] = { NULL }; - int i = 0; - g_autofree char *commit_flags_string = NULL; - - if (commit_flags & DRM_MODE_ATOMIC_NONBLOCK) - commit_flag_strings[i++] = "ATOMIC_NONBLOCK"; - if (commit_flags & DRM_MODE_ATOMIC_ALLOW_MODESET) - commit_flag_strings[i++] = "ATOMIC_ALLOW_MODESET"; - if (commit_flags & DRM_MODE_PAGE_FLIP_EVENT) - commit_flag_strings[i++] = "PAGE_FLIP_EVENT"; - - commit_flags_string = g_strjoinv ("|", (char **) commit_flag_strings); - strncpy (static_commit_flags_string, commit_flags_string, - (sizeof static_commit_flags_string) - 1); - - return static_commit_flags_string; -} - -static gboolean -disable_connectors (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_connectors (impl_device); l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_CRTC_ID, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -disable_planes (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_planes (impl_device); l; l = l->next) - { - MetaKmsPlane *plane = l->data; - - if (!add_plane_property (impl_device, - plane, req, - META_KMS_PLANE_PROP_CRTC_ID, - 0, - error)) - return FALSE; - - if (!add_plane_property (impl_device, - plane, req, - META_KMS_PLANE_PROP_FB_ID, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -disable_crtcs (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_crtcs (impl_device); l; l = l->next) - { - MetaKmsCrtc *crtc = l->data; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_ACTIVE, - 0, - error)) - return FALSE; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_MODE_ID, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -disable_planes_and_connectors (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - if (!disable_connectors (impl_device, req, error)) - return FALSE; - if (!disable_planes (impl_device, req, error)) - return FALSE; - - return TRUE; -} - -static gboolean -process_power_save (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - if (!disable_connectors (impl_device, req, error)) - return FALSE; - if (!disable_planes (impl_device, req, error)) - return FALSE; - if (!disable_crtcs (impl_device, req, error)) - return FALSE; - - return TRUE; -} - -static MetaKmsFeedback * -meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) -{ - GError *error = NULL; - GList *failed_planes = NULL; - drmModeAtomicReq *req; - g_autoptr (GArray) blob_ids = NULL; - int fd; - uint32_t commit_flags = 0; - int ret; - - blob_ids = g_array_new (FALSE, TRUE, sizeof (uint32_t)); - - meta_topic (META_DEBUG_KMS, - "[atomic] Processing update %" G_GUINT64_FORMAT, - meta_kms_update_get_sequence_number (update)); - - req = drmModeAtomicAlloc (); - if (!req) - { - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to create atomic transaction request: %s", - g_strerror (errno)); - goto err; - } - - if (meta_kms_update_get_mode_sets (update)) - { - if (!disable_planes_and_connectors (impl_device, req, &error)) - goto err; - } - - if (meta_kms_update_is_power_save (update)) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Entering power save mode for %s", - meta_kms_impl_device_get_path (impl_device)); - - if (!process_power_save (impl_device, req, &error)) - goto err; - - commit_flags = DRM_MODE_ATOMIC_ALLOW_MODESET; - goto commit; - } - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_connector_updates (update), - NULL, - process_connector_update, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_mode_sets (update), - NULL, - process_mode_set, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_plane_assignments (update), - NULL, - process_plane_assignment, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_crtc_gammas (update), - NULL, - process_crtc_gamma, - &error)) - goto err; - - if (meta_kms_update_get_mode_sets (update)) - commit_flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; - else - commit_flags |= DRM_MODE_ATOMIC_NONBLOCK; - - if (meta_kms_update_get_page_flip_listeners (update)) - commit_flags |= DRM_MODE_PAGE_FLIP_EVENT; - -commit: - meta_topic (META_DEBUG_KMS, - "[atomic] Committing update %" G_GUINT64_FORMAT ", flags: %s", - meta_kms_update_get_sequence_number (update), - commit_flags_string (commit_flags)); - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModeAtomicCommit (fd, req, commit_flags, impl_device); - drmModeAtomicFree (req); - if (ret < 0) - { - g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicCommit: %s", g_strerror (-ret)); - goto err; - } - - process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_page_flip_listeners (update), - NULL, - process_page_flip_listener, - NULL); - - release_blob_ids (impl_device, blob_ids); - - return meta_kms_feedback_new_passed (NULL); - -err: - meta_topic (META_DEBUG_KMS, "[atomic] KMS update failed: %s", error->message); - - if (!(flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR)) - { - process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_page_flip_listeners (update), - error, - discard_page_flip_listener, - NULL); - } - - release_blob_ids (impl_device, blob_ids); - - return meta_kms_feedback_new_failed (failed_planes, error); -} - -static void -meta_kms_impl_device_atomic_handle_page_flip_callback (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data) -{ - meta_kms_page_flip_data_flipped_in_impl (page_flip_data); -} - -static void -meta_kms_impl_device_atomic_discard_pending_page_flips (MetaKmsImplDevice *impl_device) -{ -} - -static gboolean -dispose_page_flip_data (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = value; - MetaKmsImplDevice *impl_device = user_data; - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL); - meta_kms_impl_device_unhold_fd (impl_device); - - return TRUE; -} - -static void -meta_kms_impl_device_atomic_prepare_shutdown (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = - META_KMS_IMPL_DEVICE_ATOMIC (impl_device); - - g_hash_table_foreach_remove (impl_device_atomic->page_flip_datas, - dispose_page_flip_data, - impl_device); -} - -static void -meta_kms_impl_device_atomic_finalize (GObject *object) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = - META_KMS_IMPL_DEVICE_ATOMIC (object); - - g_assert (g_hash_table_size (impl_device_atomic->page_flip_datas) == 0); - - g_hash_table_unref (impl_device_atomic->page_flip_datas); - - G_OBJECT_CLASS (meta_kms_impl_device_atomic_parent_class)->finalize (object); -} - -static MetaDeviceFile * -meta_kms_impl_device_atomic_open_device_file (MetaKmsImplDevice *impl_device, - const char *path, - GError **error) -{ - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - MetaBackend *backend = meta_kms_get_backend (kms); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - g_autoptr (MetaDeviceFile) device_file = NULL; - - device_file = meta_device_pool_open (device_pool, path, - META_DEVICE_FILE_FLAG_TAKE_CONTROL, - error); - if (!device_file) - return NULL; - - if (!meta_device_file_has_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_ATOMIC)) - { - int fd = meta_device_file_get_fd (device_file); - - g_warn_if_fail (!meta_device_file_has_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_SIMPLE)); - - if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED, - "DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported"); - return NULL; - } - - if (drmSetClientCap (fd, DRM_CLIENT_CAP_ATOMIC, 1) != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED, - "DRM_CLIENT_CAP_ATOMIC not supported"); - return NULL; - } - - meta_device_file_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_ATOMIC); - } - - return g_steal_pointer (&device_file); -} - -static gboolean -is_atomic_allowed (const char *driver_name) -{ - const char *atomic_driver_deny_list[] = { - "qxl", - "vmwgfx", - "vboxvideo", - "nvidia-drm", - NULL, - }; - - return !g_strv_contains (atomic_driver_deny_list, driver_name); -} - -static gboolean -meta_kms_impl_device_atomic_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable); - const char *atomic_kms_enable_env; - - atomic_kms_enable_env = getenv ("MUTTER_DEBUG_ENABLE_ATOMIC_KMS"); - if (atomic_kms_enable_env && g_strcmp0 (atomic_kms_enable_env, "1") != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_USER_INHIBITED, - "Atomic mode setting disable via env var"); - return FALSE; - } - - if (!initable_parent_iface->init (initable, cancellable, error)) - return FALSE; - - if (!is_atomic_allowed (meta_kms_impl_device_get_driver_name (impl_device))) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_DENY_LISTED, - "Atomic mode setting disable via driver deny list"); - return FALSE; - } - - if (!meta_kms_impl_device_init_mode_setting (impl_device, error)) - return FALSE; - - g_message ("Added device '%s' (%s) using atomic mode setting.", - meta_kms_impl_device_get_path (impl_device), - meta_kms_impl_device_get_driver_name (impl_device)); - - return TRUE; -} - -static void -meta_kms_impl_device_atomic_init (MetaKmsImplDeviceAtomic *impl_device_atomic) -{ - impl_device_atomic->page_flip_datas = g_hash_table_new (NULL, NULL); -} - -static void -initable_iface_init (GInitableIface *iface) -{ - initable_parent_iface = g_type_interface_peek_parent (iface); - - iface->init = meta_kms_impl_device_atomic_initable_init; -} - -static void -meta_kms_impl_device_atomic_class_init (MetaKmsImplDeviceAtomicClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaKmsImplDeviceClass *impl_device_class = - META_KMS_IMPL_DEVICE_CLASS (klass); - - object_class->finalize = meta_kms_impl_device_atomic_finalize; - - impl_device_class->open_device_file = - meta_kms_impl_device_atomic_open_device_file; - impl_device_class->setup_drm_event_context = - meta_kms_impl_device_atomic_setup_drm_event_context; - impl_device_class->process_update = - meta_kms_impl_device_atomic_process_update; - impl_device_class->handle_page_flip_callback = - meta_kms_impl_device_atomic_handle_page_flip_callback; - impl_device_class->discard_pending_page_flips = - meta_kms_impl_device_atomic_discard_pending_page_flips; - impl_device_class->prepare_shutdown = - meta_kms_impl_device_atomic_prepare_shutdown; -} diff --git a/src/backends/native/meta-kms-impl-device-atomic.h b/src/backends/native/meta-kms-impl-device-atomic.h deleted file mode 100644 index 74658797c..000000000 --- a/src/backends/native/meta-kms-impl-device-atomic.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_IMPL_DEVICE_ATOMIC_H -#define META_KMS_IMPL_DEVICE_ATOMIC_H - -#include "backends/native/meta-kms-impl-device.h" - -#define META_TYPE_KMS_IMPL_DEVICE_ATOMIC (meta_kms_impl_device_atomic_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsImplDeviceAtomic, meta_kms_impl_device_atomic, - META, KMS_IMPL_DEVICE_ATOMIC, MetaKmsImplDevice) - -#endif /* META_KMS_IMPL_DEVICE_ATOMIC_H */ diff --git a/src/backends/native/meta-kms-impl-device-dummy.c b/src/backends/native/meta-kms-impl-device-dummy.c deleted file mode 100644 index 02583bbeb..000000000 --- a/src/backends/native/meta-kms-impl-device-dummy.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-impl-device-dummy.h" - -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-kms.h" - -struct _MetaKmsImplDeviceDummy -{ - MetaKmsImplDevice parent; -}; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceDummy, - meta_kms_impl_device_dummy, - META_TYPE_KMS_IMPL_DEVICE, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static void -meta_kms_impl_device_dummy_discard_pending_page_flips (MetaKmsImplDevice *impl_device) -{ -} - -static MetaDeviceFile * -meta_kms_impl_device_dummy_open_device_file (MetaKmsImplDevice *impl_device, - const char *path, - GError **error) -{ - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - MetaBackend *backend = meta_kms_get_backend (kms); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - g_autoptr (MetaDeviceFile) device_file = NULL; - int fd; - g_autofree char *render_node_path = NULL; - - device_file = meta_device_pool_open (device_pool, path, - META_DEVICE_FILE_FLAG_NONE, - error); - if (!device_file) - return NULL; - - fd = meta_device_file_get_fd (device_file); - render_node_path = drmGetRenderDeviceNameFromFd (fd); - if (!render_node_path) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't find render node device for '%s' (%s)", - meta_kms_impl_device_get_path (impl_device), - meta_kms_impl_device_get_driver_name (impl_device)); - return NULL; - } - - meta_topic (META_DEBUG_KMS, "Found render node '%s' from '%s'", - render_node_path, path); - - return meta_device_pool_open (device_pool, render_node_path, - META_DEVICE_FILE_FLAG_NONE, - error); -} - -static gboolean -meta_kms_impl_device_dummy_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable); - - if (!initable_parent_iface->init (initable, cancellable, error)) - return FALSE; - - g_message ("Added device '%s' (%s) using no mode setting.", - meta_kms_impl_device_get_path (impl_device), - meta_kms_impl_device_get_driver_name (impl_device)); - - return TRUE; -} - -static void -initable_iface_init (GInitableIface *iface) -{ - initable_parent_iface = g_type_interface_peek_parent (iface); - - iface->init = meta_kms_impl_device_dummy_initable_init; -} - -static void -meta_kms_impl_device_dummy_init (MetaKmsImplDeviceDummy *impl_device_dummy) -{ -} - -static void -meta_kms_impl_device_dummy_class_init (MetaKmsImplDeviceDummyClass *klass) -{ - MetaKmsImplDeviceClass *impl_device_class = - META_KMS_IMPL_DEVICE_CLASS (klass); - - impl_device_class->open_device_file = - meta_kms_impl_device_dummy_open_device_file; - impl_device_class->discard_pending_page_flips = - meta_kms_impl_device_dummy_discard_pending_page_flips; -} diff --git a/src/backends/native/meta-kms-impl-device-dummy.h b/src/backends/native/meta-kms-impl-device-dummy.h deleted file mode 100644 index 9576939ad..000000000 --- a/src/backends/native/meta-kms-impl-device-dummy.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#ifndef META_KMS_IMPL_DEVICE_DUMMY_H -#define META_KMS_IMPL_DEVICE_DUMMY_H - -#include "backends/native/meta-kms-impl-device.h" - -#define META_TYPE_KMS_IMPL_DEVICE_DUMMY (meta_kms_impl_device_dummy_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsImplDeviceDummy, meta_kms_impl_device_dummy, - META, KMS_IMPL_DEVICE_DUMMY, - MetaKmsImplDevice) - -#endif /* META_KMS_IMPL_DEVICE_DUMMY_H */ diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c deleted file mode 100644 index 28d512720..000000000 --- a/src/backends/native/meta-kms-impl-device-simple.c +++ /dev/null @@ -1,1678 +0,0 @@ -/* - * Copyright (C) 2019-2020 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-impl-device-simple.h" - -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-kms-connector-private.h" -#include "backends/native/meta-kms-crtc-private.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-plane-private.h" -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-update-private.h" -#include "backends/native/meta-kms-utils.h" - -typedef gboolean (* MetaKmsSimpleProcessFunc) (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - gpointer entry_data, - GError **error); - -typedef struct _CachedModeSet -{ - GList *connectors; - drmModeModeInfo *drm_mode; -} CachedModeSet; - -struct _MetaKmsImplDeviceSimple -{ - MetaKmsImplDevice parent; - - GSource *mode_set_fallback_feedback_source; - GList *mode_set_fallback_page_flip_datas; - - GList *pending_page_flip_retries; - GSource *retry_page_flips_source; - - GList *postponed_page_flip_datas; - GList *postponed_mode_set_fallback_datas; - - GList *posted_page_flip_datas; - - GHashTable *cached_mode_sets; -}; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceSimple, meta_kms_impl_device_simple, - META_TYPE_KMS_IMPL_DEVICE, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static void -flush_postponed_page_flip_datas (MetaKmsImplDeviceSimple *impl_device_simple); - -static gboolean -get_connector_property (MetaKmsImplDevice *impl_device, - MetaKmsConnector *connector, - MetaKmsConnectorProp prop, - uint64_t *value, - GError **error) -{ - uint32_t prop_id; - int fd; - drmModeConnector *drm_connector; - int i; - gboolean found; - - prop_id = meta_kms_connector_get_prop_id (connector, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Property (%s) not found on connector %u", - meta_kms_connector_get_prop_name (connector, prop), - meta_kms_connector_get_id (connector)); - return FALSE; - } - - fd = meta_kms_impl_device_get_fd (impl_device); - - drm_connector = drmModeGetConnector (fd, - meta_kms_connector_get_id (connector)); - if (!drm_connector) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to get connector %u resources: %s", - meta_kms_connector_get_id (connector), - g_strerror (errno)); - return FALSE; - } - - found = FALSE; - for (i = 0; i < drm_connector->count_props; i++) - { - if (drm_connector->props[i] == prop_id) - { - *value = drm_connector->prop_values[i]; - found = TRUE; - break; - } - } - - drmModeFreeConnector (drm_connector); - - if (!found) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "Connector property %u not found", prop_id); - return FALSE; - } - - return TRUE; -} - -static gboolean -set_connector_property (MetaKmsImplDevice *impl_device, - MetaKmsConnector *connector, - MetaKmsConnectorProp prop, - uint64_t value, - GError **error) -{ - uint32_t prop_id; - int fd; - int ret; - - prop_id = meta_kms_connector_get_prop_id (connector, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Property (%s) not found on connector %u", - meta_kms_connector_get_prop_name (connector, prop), - meta_kms_connector_get_id (connector)); - return FALSE; - } - - fd = meta_kms_impl_device_get_fd (impl_device); - - ret = drmModeObjectSetProperty (fd, - meta_kms_connector_get_id (connector), - DRM_MODE_OBJECT_CONNECTOR, - prop_id, - value); - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "Failed to set connector %u property %u: %s", - meta_kms_connector_get_id (connector), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -process_power_save (MetaKmsImplDevice *impl_device, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_connectors (impl_device); l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - meta_topic (META_DEBUG_KMS, - "[simple] Setting DPMS of connector %u (%s) to OFF", - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device)); - - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_DPMS, - DRM_MODE_DPMS_OFF, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -process_connector_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - gpointer update_entry, - GError **error) -{ - MetaKmsConnectorUpdate *connector_update = update_entry; - MetaKmsConnector *connector = connector_update->connector; - - if (connector_update->underscanning.has_update && - connector_update->underscanning.is_active) - { - meta_topic (META_DEBUG_KMS, - "[simple] Setting underscanning on connector %u (%s) to " - "%" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device), - connector_update->underscanning.hborder, - connector_update->underscanning.vborder); - - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - 1, - error)) - return FALSE; - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER, - connector_update->underscanning.hborder, - error)) - return FALSE; - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER, - connector_update->underscanning.vborder, - error)) - return FALSE; - } - else if (connector_update->underscanning.has_update) - { - meta_topic (META_DEBUG_KMS, - "[simple] Unsetting underscanning on connector %u (%s)", - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device)); - - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static CachedModeSet * -cached_mode_set_new (GList *connectors, - const drmModeModeInfo *drm_mode) -{ - CachedModeSet *cached_mode_set; - - cached_mode_set = g_new0 (CachedModeSet, 1); - *cached_mode_set = (CachedModeSet) { - .connectors = g_list_copy (connectors), - .drm_mode = g_memdup2 (drm_mode, sizeof *drm_mode), - }; - - return cached_mode_set; -} - -static void -cached_mode_set_free (CachedModeSet *cached_mode_set) -{ - g_list_free (cached_mode_set->connectors); - g_free (cached_mode_set->drm_mode); - g_free (cached_mode_set); -} - -static void -fill_connector_ids_array (GList *connectors, - uint32_t **out_connectors, - int *out_n_connectors) -{ - GList *l; - int i; - - *out_n_connectors = g_list_length (connectors); - *out_connectors = g_new0 (uint32_t, *out_n_connectors); - i = 0; - for (l = connectors; l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - (*out_connectors)[i++] = meta_kms_connector_get_id (connector); - } -} - -static gboolean -set_plane_rotation (MetaKmsImplDevice *impl_device, - MetaKmsPlane *plane, - uint64_t rotation, - GError **error) -{ - int fd; - uint32_t rotation_prop_id; - int ret; - - fd = meta_kms_impl_device_get_fd (impl_device); - - rotation_prop_id = meta_kms_plane_get_prop_id (plane, - META_KMS_PLANE_PROP_ROTATION); - - meta_topic (META_DEBUG_KMS, - "[simple] Setting plane %u (%s) rotation to %" G_GUINT64_FORMAT, - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - rotation); - - ret = drmModeObjectSetProperty (fd, - meta_kms_plane_get_id (plane), - DRM_MODE_OBJECT_PLANE, - rotation_prop_id, - rotation); - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "Failed to rotation property (%u) to %" G_GUINT64_FORMAT - " on plane %u: %s", - rotation_prop_id, - rotation, - meta_kms_plane_get_id (plane), - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -process_mode_set (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - gpointer update_entry, - GError **error) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - MetaKmsModeSet *mode_set = update_entry; - MetaKmsCrtc *crtc = mode_set->crtc; - g_autofree uint32_t *connectors = NULL; - int n_connectors; - MetaKmsPlaneAssignment *plane_assignment; - drmModeModeInfo *drm_mode; - uint32_t x, y; - uint32_t fb_id; - int fd; - int ret; - - crtc = mode_set->crtc; - - if (mode_set->mode) - { - MetaDrmBuffer *buffer; - GList *l; - - drm_mode = g_alloca (sizeof *drm_mode); - *drm_mode = *meta_kms_mode_get_drm_mode (mode_set->mode); - - fill_connector_ids_array (mode_set->connectors, - &connectors, - &n_connectors); - - plane_assignment = meta_kms_update_get_primary_plane_assignment (update, - crtc); - if (!plane_assignment) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing primary plane assignment for legacy mode set on CRTC %u", - meta_kms_crtc_get_id (crtc)); - return FALSE; - } - - x = meta_fixed_16_to_int (plane_assignment->src_rect.x); - y = meta_fixed_16_to_int (plane_assignment->src_rect.y); - - if (plane_assignment->rotation) - { - if (!set_plane_rotation (impl_device, - plane_assignment->plane, - plane_assignment->rotation, - error)) - return FALSE; - } - - buffer = plane_assignment->buffer; - fb_id = meta_drm_buffer_get_fb_id (buffer); - - for (l = mode_set->connectors; l; l = l->next) - { - MetaKmsConnector *connector = l->data; - uint64_t dpms_value; - - if (!get_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_DPMS, - &dpms_value, - error)) - return FALSE; - - if (dpms_value != DRM_MODE_DPMS_ON) - { - meta_topic (META_DEBUG_KMS, - "[simple] Setting DPMS of connector %u (%s) to ON", - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device)); - - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_DPMS, - DRM_MODE_DPMS_ON, - error)) - return FALSE; - } - } - - meta_topic (META_DEBUG_KMS, - "[simple] Setting mode of CRTC %u (%s) to %s", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - drm_mode->name); - } - else - { - drm_mode = NULL; - x = y = 0; - n_connectors = 0; - connectors = NULL; - fb_id = 0; - - meta_topic (META_DEBUG_KMS, - "[simple] Unsetting mode of CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - } - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModeSetCrtc (fd, - meta_kms_crtc_get_id (crtc), - fb_id, - x, y, - connectors, n_connectors, - drm_mode); - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "Failed to set mode %s on CRTC %u: %s", - drm_mode ? drm_mode->name : "off", - meta_kms_crtc_get_id (crtc), - g_strerror (-ret)); - return FALSE; - } - - if (drm_mode) - { - g_hash_table_replace (impl_device_simple->cached_mode_sets, - crtc, - cached_mode_set_new (mode_set->connectors, - drm_mode)); - } - else - { - g_hash_table_remove (impl_device_simple->cached_mode_sets, crtc); - } - - return TRUE; -} - -static gboolean -process_crtc_gamma (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - gpointer update_entry, - GError **error) -{ - MetaKmsCrtcGamma *gamma = update_entry; - MetaKmsCrtc *crtc = gamma->crtc; - int fd; - int ret; - - meta_topic (META_DEBUG_KMS, - "[simple] Setting CRTC %u (%s) gamma, size: %d", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - gamma->size); - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModeCrtcSetGamma (fd, meta_kms_crtc_get_id (crtc), - gamma->size, - gamma->red, - gamma->green, - gamma->blue); - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeCrtcSetGamma on CRTC %u failed: %s", - meta_kms_crtc_get_id (crtc), - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -is_timestamp_earlier_than (uint64_t ts1, - uint64_t ts2) -{ - if (ts1 == ts2) - return FALSE; - else - return ts2 - ts1 < UINT64_MAX / 2; -} - -typedef struct _RetryPageFlipData -{ - MetaKmsCrtc *crtc; - uint32_t fb_id; - MetaKmsPageFlipData *page_flip_data; - float refresh_rate; - uint64_t retry_time_us; - MetaKmsCustomPageFlip *custom_page_flip; -} RetryPageFlipData; - -static void -retry_page_flip_data_free (RetryPageFlipData *retry_page_flip_data) -{ - g_assert (!retry_page_flip_data->page_flip_data); - g_clear_pointer (&retry_page_flip_data->custom_page_flip, - meta_kms_custom_page_flip_free); - g_free (retry_page_flip_data); -} - -static CachedModeSet * -get_cached_mode_set (MetaKmsImplDeviceSimple *impl_device_simple, - MetaKmsCrtc *crtc) -{ - return g_hash_table_lookup (impl_device_simple->cached_mode_sets, crtc); -} - -static float -get_cached_crtc_refresh_rate (MetaKmsImplDeviceSimple *impl_device_simple, - MetaKmsCrtc *crtc) -{ - CachedModeSet *cached_mode_set; - - cached_mode_set = g_hash_table_lookup (impl_device_simple->cached_mode_sets, - crtc); - g_assert (cached_mode_set); - - return meta_calculate_drm_mode_refresh_rate (cached_mode_set->drm_mode); -} - -#define meta_assert_in_kms_impl(kms) \ - g_assert (meta_kms_in_impl_task (kms)) - -static gboolean -retry_page_flips (gpointer user_data) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (user_data); - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple); - uint64_t now_us; - GList *l; - - now_us = g_source_get_time (impl_device_simple->retry_page_flips_source); - - l = impl_device_simple->pending_page_flip_retries; - while (l) - { - RetryPageFlipData *retry_page_flip_data = l->data; - MetaKmsCrtc *crtc = retry_page_flip_data->crtc; - GList *l_next = l->next; - int fd; - int ret; - MetaKmsPageFlipData *page_flip_data; - MetaKmsCustomPageFlip *custom_page_flip; - - if (is_timestamp_earlier_than (now_us, - retry_page_flip_data->retry_time_us)) - { - l = l_next; - continue; - } - - custom_page_flip = retry_page_flip_data->custom_page_flip; - if (custom_page_flip) - { - meta_topic (META_DEBUG_KMS, - "[simple] Retrying custom page flip on CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - ret = custom_page_flip->func (custom_page_flip->user_data, - retry_page_flip_data->page_flip_data); - } - else - { - meta_topic (META_DEBUG_KMS, - "[simple] Retrying page flip on CRTC %u (%s) with %u", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - retry_page_flip_data->fb_id); - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModePageFlip (fd, - meta_kms_crtc_get_id (crtc), - retry_page_flip_data->fb_id, - DRM_MODE_PAGE_FLIP_EVENT, - retry_page_flip_data->page_flip_data); - } - - if (ret == -EBUSY) - { - float refresh_rate; - - meta_topic (META_DEBUG_KMS, - "[simple] Rescheduling page flip retry on CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - - refresh_rate = - get_cached_crtc_refresh_rate (impl_device_simple, crtc); - retry_page_flip_data->retry_time_us += - (uint64_t) (G_USEC_PER_SEC / refresh_rate); - l = l_next; - continue; - } - - impl_device_simple->pending_page_flip_retries = - g_list_remove_link (impl_device_simple->pending_page_flip_retries, l); - - page_flip_data = g_steal_pointer (&retry_page_flip_data->page_flip_data); - if (ret != 0) - { - g_autoptr (GError) error = NULL; - - g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModePageFlip on CRTC %u failed: %s", - meta_kms_crtc_get_id (crtc), - g_strerror (-ret)); - if (!g_error_matches (error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_critical ("Failed to page flip: %s", error->message); - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, error); - meta_kms_impl_device_unhold_fd (impl_device); - } - else - { - impl_device_simple->posted_page_flip_datas = - g_list_prepend (impl_device_simple->posted_page_flip_datas, - page_flip_data); - } - - retry_page_flip_data_free (retry_page_flip_data); - - l = l_next; - } - - if (impl_device_simple->pending_page_flip_retries) - { - GList *l; - uint64_t earliest_retry_time_us = 0; - - for (l = impl_device_simple->pending_page_flip_retries; l; l = l->next) - { - RetryPageFlipData *retry_page_flip_data = l->data; - - if (l == impl_device_simple->pending_page_flip_retries || - is_timestamp_earlier_than (retry_page_flip_data->retry_time_us, - earliest_retry_time_us)) - earliest_retry_time_us = retry_page_flip_data->retry_time_us; - } - - g_source_set_ready_time (impl_device_simple->retry_page_flips_source, - earliest_retry_time_us); - return G_SOURCE_CONTINUE; - } - else - { - g_clear_pointer (&impl_device_simple->retry_page_flips_source, - g_source_unref); - - flush_postponed_page_flip_datas (impl_device_simple); - - return G_SOURCE_REMOVE; - } -} - -static void -schedule_retry_page_flip (MetaKmsImplDeviceSimple *impl_device_simple, - MetaKmsCrtc *crtc, - uint32_t fb_id, - float refresh_rate, - MetaKmsPageFlipData *page_flip_data, - MetaKmsCustomPageFlip *custom_page_flip) -{ - RetryPageFlipData *retry_page_flip_data; - uint64_t now_us; - uint64_t retry_time_us; - - now_us = g_get_monotonic_time (); - retry_time_us = now_us + (uint64_t) (G_USEC_PER_SEC / refresh_rate); - - retry_page_flip_data = g_new0 (RetryPageFlipData, 1); - *retry_page_flip_data = (RetryPageFlipData) { - .crtc = crtc, - .fb_id = fb_id, - .page_flip_data = page_flip_data, - .refresh_rate = refresh_rate, - .retry_time_us = retry_time_us, - .custom_page_flip = custom_page_flip, - }; - - if (!impl_device_simple->retry_page_flips_source) - { - MetaKmsImplDevice *impl_device = - META_KMS_IMPL_DEVICE (impl_device_simple); - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - GSource *source; - - source = meta_kms_add_source_in_impl (kms, retry_page_flips, - impl_device_simple, NULL); - g_source_set_ready_time (source, retry_time_us); - - impl_device_simple->retry_page_flips_source = source; - } - else - { - GList *l; - - for (l = impl_device_simple->pending_page_flip_retries; l; l = l->next) - { - RetryPageFlipData *pending_retry_page_flip_data = l->data; - uint64_t pending_retry_time_us = - pending_retry_page_flip_data->retry_time_us; - - if (is_timestamp_earlier_than (retry_time_us, pending_retry_time_us)) - { - g_source_set_ready_time (impl_device_simple->retry_page_flips_source, - retry_time_us); - break; - } - } - } - - impl_device_simple->pending_page_flip_retries = - g_list_append (impl_device_simple->pending_page_flip_retries, - retry_page_flip_data); -} - -static void -dispatch_page_flip_datas (GList **page_flip_datas, - GFunc func, - gpointer user_data) -{ - g_list_foreach (*page_flip_datas, func, user_data); - g_clear_pointer (page_flip_datas, g_list_free); -} - -static gboolean -mode_set_fallback_feedback_idle (gpointer user_data) -{ - MetaKmsImplDeviceSimple *impl_device_simple = user_data; - - g_clear_pointer (&impl_device_simple->mode_set_fallback_feedback_source, - g_source_unref); - - if (impl_device_simple->pending_page_flip_retries) - { - impl_device_simple->postponed_mode_set_fallback_datas = - g_steal_pointer (&impl_device_simple->mode_set_fallback_page_flip_datas); - } - else - { - dispatch_page_flip_datas (&impl_device_simple->mode_set_fallback_page_flip_datas, - (GFunc) meta_kms_page_flip_data_mode_set_fallback_in_impl, - NULL); - } - - return G_SOURCE_REMOVE; -} - -static gboolean -mode_set_fallback (MetaKmsImplDeviceSimple *impl_device_simple, - MetaKmsUpdate *update, - MetaKmsPlaneAssignment *plane_assignment, - MetaKmsPageFlipData *page_flip_data, - GError **error) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple); - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - MetaKmsCrtc *crtc = meta_kms_page_flip_data_get_crtc (page_flip_data); - CachedModeSet *cached_mode_set; - g_autofree uint32_t *connectors = NULL; - int n_connectors; - uint32_t fb_id; - uint32_t x, y; - int fd; - int ret; - - cached_mode_set = g_hash_table_lookup (impl_device_simple->cached_mode_sets, - crtc); - if (!cached_mode_set) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing mode set for page flip fallback"); - return FALSE; - } - - fill_connector_ids_array (cached_mode_set->connectors, - &connectors, - &n_connectors); - - fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer); - - x = meta_fixed_16_to_int (plane_assignment->src_rect.x); - y = meta_fixed_16_to_int (plane_assignment->src_rect.y); - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModeSetCrtc (fd, - meta_kms_crtc_get_id (crtc), - fb_id, - x, y, - connectors, n_connectors, - cached_mode_set->drm_mode); - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeSetCrtc mode '%s' on CRTC %u failed: %s", - cached_mode_set->drm_mode->name, - meta_kms_crtc_get_id (crtc), - g_strerror (-ret)); - return FALSE; - } - - if (!impl_device_simple->mode_set_fallback_feedback_source) - { - GSource *source; - - source = meta_kms_add_source_in_impl (kms, - mode_set_fallback_feedback_idle, - impl_device_simple, - NULL); - impl_device_simple->mode_set_fallback_feedback_source = source; - } - - impl_device_simple->mode_set_fallback_page_flip_datas = - g_list_prepend (impl_device_simple->mode_set_fallback_page_flip_datas, - page_flip_data); - - return TRUE; -} - -static gboolean -symbolic_page_flip_idle (gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = user_data; - MetaKmsImplDevice *impl_device; - MetaKmsCrtc *crtc; - - impl_device = meta_kms_page_flip_data_get_impl_device (page_flip_data); - crtc = meta_kms_page_flip_data_get_crtc (page_flip_data); - - meta_topic (META_DEBUG_KMS, - "[simple] Handling symbolic page flip callback from %s, data: %p, CRTC: %u", - meta_kms_impl_device_get_path (impl_device), - page_flip_data, - meta_kms_crtc_get_id (crtc)); - - meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data); - - return G_SOURCE_REMOVE; -} - -static gboolean -dispatch_page_flip (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsPageFlipData *page_flip_data, - GError **error) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - MetaKmsCrtc *crtc; - MetaKmsPlaneAssignment *plane_assignment; - g_autoptr (MetaKmsCustomPageFlip) custom_page_flip = NULL; - int fd; - int ret; - - crtc = meta_kms_page_flip_data_get_crtc (page_flip_data); - plane_assignment = meta_kms_update_get_primary_plane_assignment (update, - crtc); - - custom_page_flip = meta_kms_update_take_custom_page_flip_func (update); - - if (!plane_assignment && !custom_page_flip) - { - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - GSource *source; - - meta_kms_page_flip_data_make_symbolic (page_flip_data); - - source = meta_kms_add_source_in_impl (kms, - symbolic_page_flip_idle, - page_flip_data, - NULL); - - g_source_set_ready_time (source, 0); - g_source_unref (source); - - return TRUE; - } - - fd = meta_kms_impl_device_get_fd (impl_device); - if (custom_page_flip) - { - meta_topic (META_DEBUG_KMS, - "[simple] Invoking custom page flip on CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - ret = custom_page_flip->func (custom_page_flip->user_data, - page_flip_data); - } - else - { - uint32_t fb_id; - - fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer); - - meta_topic (META_DEBUG_KMS, - "[simple] Page flipping CRTC %u (%s) with %u, data: %p", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - fb_id, - page_flip_data); - - ret = drmModePageFlip (fd, - meta_kms_crtc_get_id (crtc), - fb_id, - DRM_MODE_PAGE_FLIP_EVENT, - page_flip_data); - } - - if (ret == -EBUSY) - { - CachedModeSet *cached_mode_set; - - meta_topic (META_DEBUG_KMS, - "[simple] Scheduling page flip retry on CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - - cached_mode_set = get_cached_mode_set (impl_device_simple, crtc); - if (cached_mode_set) - { - uint32_t fb_id; - drmModeModeInfo *drm_mode; - float refresh_rate; - - if (plane_assignment) - fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer); - else - fb_id = 0; - drm_mode = cached_mode_set->drm_mode; - refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode); - meta_kms_impl_device_hold_fd (impl_device); - schedule_retry_page_flip (impl_device_simple, - crtc, - fb_id, - refresh_rate, - page_flip_data, - g_steal_pointer (&custom_page_flip)); - return TRUE; - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Page flip of %u failed, and no mode set available", - meta_kms_crtc_get_id (crtc)); - return FALSE; - } - } - else if (ret == -EINVAL) - { - meta_topic (META_DEBUG_KMS, - "[simple] Falling back to mode set on CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - - return mode_set_fallback (impl_device_simple, - update, - plane_assignment, - page_flip_data, - error); - } - else if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModePageFlip on CRTC %u failed: %s", - meta_kms_crtc_get_id (crtc), - g_strerror (-ret)); - return FALSE; - } - else - { - meta_kms_impl_device_hold_fd (impl_device); - - impl_device_simple->posted_page_flip_datas = - g_list_prepend (impl_device_simple->posted_page_flip_datas, - page_flip_data); - - return TRUE; - } -} - -static GList * -generate_page_flip_datas (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update) -{ - GList *listeners; - GList *page_flip_datas = NULL; - - listeners = g_list_copy (meta_kms_update_get_page_flip_listeners (update)); - - while (listeners) - { - MetaKmsPageFlipListener *listener = listeners->data; - MetaKmsCrtc *crtc = listener->crtc; - MetaKmsPageFlipData *page_flip_data; - gpointer user_data; - GDestroyNotify destroy_notify; - GList *l; - - page_flip_data = meta_kms_page_flip_data_new (impl_device, crtc); - page_flip_datas = g_list_append (page_flip_datas, page_flip_data); - - user_data = g_steal_pointer (&listener->user_data); - destroy_notify = g_steal_pointer (&listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - listener->vtable, - listener->flags, - user_data, - destroy_notify); - - listeners = g_list_delete_link (listeners, listeners); - - l = listeners; - while (l) - { - MetaKmsPageFlipListener *other_listener = l->data; - GList *l_next = l->next; - - if (other_listener->crtc == crtc) - { - gpointer other_user_data; - GDestroyNotify other_destroy_notify; - - other_user_data = g_steal_pointer (&other_listener->user_data); - other_destroy_notify = - g_steal_pointer (&other_listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - other_listener->vtable, - other_listener->flags, - other_user_data, - other_destroy_notify); - listeners = g_list_delete_link (listeners, l); - } - - l = l_next; - } - } - - return page_flip_datas; -} - -static gboolean -maybe_dispatch_page_flips (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - GList **failed_planes, - MetaKmsUpdateFlag flags, - GError **error) -{ - g_autoptr (GList) page_flip_datas = NULL; - GList *l; - - page_flip_datas = generate_page_flip_datas (impl_device, update); - - while (page_flip_datas) - { - g_autoptr (GList) l = NULL; - MetaKmsPageFlipData *page_flip_data; - - l = page_flip_datas; - page_flip_datas = g_list_remove_link (page_flip_datas, l); - page_flip_data = g_steal_pointer (&l->data); - - if (!dispatch_page_flip (impl_device, update, page_flip_data, error)) - { - if (!g_error_matches (*error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - { - MetaKmsCrtc *crtc = - meta_kms_page_flip_data_get_crtc (page_flip_data); - MetaKmsPlaneAssignment *plane_assignment; - MetaKmsPlaneFeedback *plane_feedback; - - plane_assignment = - meta_kms_update_get_primary_plane_assignment (update, crtc); - - plane_feedback = - meta_kms_plane_feedback_new_take_error (plane_assignment->plane, - plane_assignment->crtc, - g_error_copy (*error)); - *failed_planes = g_list_prepend (*failed_planes, plane_feedback); - } - - if (!(flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR)) - meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error); - - goto err; - } - } - - return TRUE; - -err: - if (!(flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR)) - { - for (l = page_flip_datas; l; l = l->next) - { - MetaKmsPageFlipData *page_flip_data = l->data; - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error); - } - } - g_list_free (page_flip_datas); - - return FALSE; -} - -static gboolean -process_entries (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - GList *entries, - MetaKmsSimpleProcessFunc func, - GError **error) -{ - GList *l; - - for (l = entries; l; l = l->next) - { - if (!func (impl_device, update, l->data, error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -process_cursor_plane_assignment (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsPlaneAssignment *plane_assignment, - GError **error) -{ - uint32_t crtc_id; - int fd; - - crtc_id = meta_kms_crtc_get_id (plane_assignment->crtc), - fd = meta_kms_impl_device_get_fd (impl_device); - - if (!(plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED)) - { - int width, height; - int ret = -1; - uint32_t handle_u32; - - width = plane_assignment->dst_rect.width; - height = plane_assignment->dst_rect.height; - - if (plane_assignment->buffer) - { - MetaDrmBufferGbm *buffer_gbm = - META_DRM_BUFFER_GBM (plane_assignment->buffer); - struct gbm_bo *bo; - union gbm_bo_handle handle; - - bo = meta_drm_buffer_gbm_get_bo (buffer_gbm); - handle = gbm_bo_get_handle (bo); - handle_u32 = handle.u32; - } - else - { - handle_u32 = 0; - } - - meta_topic (META_DEBUG_KMS, - "[simple] Setting HW cursor of CRTC %u (%s) to %u " - "(size: %dx%d, hot: (%d, %d))", - crtc_id, - meta_kms_impl_device_get_path (impl_device), - handle_u32, - width, height, - plane_assignment->cursor_hotspot.x, - plane_assignment->cursor_hotspot.y); - - if (plane_assignment->cursor_hotspot.is_valid) - { - ret = drmModeSetCursor2 (fd, - crtc_id, - handle_u32, - width, height, - plane_assignment->cursor_hotspot.x, - plane_assignment->cursor_hotspot.y); - } - - if (ret != 0) - { - ret = drmModeSetCursor (fd, crtc_id, - handle_u32, - width, height); - } - - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeSetCursor failed: %s", g_strerror (-ret)); - return FALSE; - } - } - - meta_topic (META_DEBUG_KMS, - "[simple] Moving HW cursor of CRTC %u (%s) to (%d, %d)", - crtc_id, - meta_kms_impl_device_get_path (impl_device), - plane_assignment->dst_rect.x, - plane_assignment->dst_rect.y); - - drmModeMoveCursor (fd, - crtc_id, - plane_assignment->dst_rect.x, - plane_assignment->dst_rect.y); - - return TRUE; -} - -static gboolean -process_plane_assignment (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsPlaneAssignment *plane_assignment, - MetaKmsPlaneFeedback **plane_feedback) -{ - MetaKmsPlane *plane; - MetaKmsPlaneType plane_type; - GError *error = NULL; - - plane = plane_assignment->plane; - plane_type = meta_kms_plane_get_plane_type (plane); - switch (plane_type) - { - case META_KMS_PLANE_TYPE_PRIMARY: - /* Handled as part of the mode-set and page flip. */ - return TRUE; - case META_KMS_PLANE_TYPE_CURSOR: - if (!process_cursor_plane_assignment (impl_device, update, - plane_assignment, - &error)) - { - *plane_feedback = - meta_kms_plane_feedback_new_take_error (plane, - plane_assignment->crtc, - g_steal_pointer (&error)); - return FALSE; - } - else - { - return TRUE; - } - case META_KMS_PLANE_TYPE_OVERLAY: - error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, - "Overlay planes cannot be assigned"); - *plane_feedback = - meta_kms_plane_feedback_new_take_error (plane, - plane_assignment->crtc, - g_steal_pointer (&error)); - return TRUE; - } - - g_assert_not_reached (); -} - -static gboolean -process_plane_assignments (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - GList **failed_planes, - GError **error) -{ - GList *l; - - for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next) - { - MetaKmsPlaneAssignment *plane_assignment = l->data; - MetaKmsPlaneFeedback *plane_feedback; - - if (!process_plane_assignment (impl_device, update, plane_assignment, - &plane_feedback)) - { - if (g_error_matches (plane_feedback->error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - { - g_propagate_error (error, - g_steal_pointer (&plane_feedback->error)); - meta_kms_plane_feedback_free (plane_feedback); - return FALSE; - } - - *failed_planes = g_list_prepend (*failed_planes, plane_feedback); - if (plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL) - { - continue; - } - else - { - g_propagate_error (error, g_error_copy (plane_feedback->error)); - return FALSE; - } - } - } - - return TRUE; -} - -static void -page_flip_handler (int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - void *user_data) -{ - MetaKmsPageFlipData *page_flip_data = user_data; - MetaKmsImplDevice *impl_device; - MetaKmsImplDeviceSimple *impl_device_simple; - MetaKmsCrtc *crtc; - - meta_kms_page_flip_data_set_timings_in_impl (page_flip_data, - sequence, tv_sec, tv_usec); - - impl_device = meta_kms_page_flip_data_get_impl_device (page_flip_data); - impl_device_simple = META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - crtc = meta_kms_page_flip_data_get_crtc (page_flip_data); - - meta_topic (META_DEBUG_KMS, - "[simple] Handling page flip callback from %s, data: %p, CRTC: %u", - meta_kms_impl_device_get_path (impl_device), - page_flip_data, - meta_kms_crtc_get_id (crtc)); - - meta_kms_impl_device_unhold_fd (impl_device); - - meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data); - impl_device_simple->posted_page_flip_datas = - g_list_remove (impl_device_simple->posted_page_flip_datas, - page_flip_data); -} - -static void -meta_kms_impl_device_simple_setup_drm_event_context (MetaKmsImplDevice *impl_device, - drmEventContext *drm_event_context) -{ - drm_event_context->version = 2; - drm_event_context->page_flip_handler = page_flip_handler; -} - -static MetaKmsFeedback * -meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) -{ - GError *error = NULL; - GList *failed_planes = NULL; - - meta_topic (META_DEBUG_KMS, - "[simple] Processing update %" G_GUINT64_FORMAT, - meta_kms_update_get_sequence_number (update)); - - if (meta_kms_update_is_power_save (update)) - { - if (!process_power_save (impl_device, &error)) - goto err; - goto out; - } - - if (!process_entries (impl_device, - update, - meta_kms_update_get_mode_sets (update), - process_mode_set, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - meta_kms_update_get_connector_updates (update), - process_connector_update, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - meta_kms_update_get_crtc_gammas (update), - process_crtc_gamma, - &error)) - goto err; - - if (!process_plane_assignments (impl_device, update, &failed_planes, &error)) - goto err; - - if (!maybe_dispatch_page_flips (impl_device, update, &failed_planes, flags, - &error)) - goto err; - -out: - return meta_kms_feedback_new_passed (failed_planes); - -err: - return meta_kms_feedback_new_failed (failed_planes, error); -} - -static void -flush_postponed_page_flip_datas (MetaKmsImplDeviceSimple *impl_device_simple) -{ - dispatch_page_flip_datas (&impl_device_simple->postponed_page_flip_datas, - (GFunc) meta_kms_page_flip_data_flipped_in_impl, - NULL); - dispatch_page_flip_datas (&impl_device_simple->postponed_mode_set_fallback_datas, - (GFunc) meta_kms_page_flip_data_mode_set_fallback_in_impl, - NULL); -} - -static void -meta_kms_impl_device_simple_handle_page_flip_callback (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - - if (impl_device_simple->pending_page_flip_retries) - { - impl_device_simple->postponed_page_flip_datas = - g_list_append (impl_device_simple->postponed_page_flip_datas, - page_flip_data); - } - else - { - meta_kms_page_flip_data_flipped_in_impl (page_flip_data); - } -} - -static void -dispose_page_flip_data (MetaKmsPageFlipData *page_flip_data, - MetaKmsImplDevice *impl_device) -{ - meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL); - meta_kms_impl_device_unhold_fd (impl_device); -} - -static void -meta_kms_impl_device_simple_discard_pending_page_flips (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - GList *l; - - if (!impl_device_simple->pending_page_flip_retries) - return; - - for (l = impl_device_simple->pending_page_flip_retries; l; l = l->next) - { - RetryPageFlipData *retry_page_flip_data = l->data; - MetaKmsPageFlipData *page_flip_data; - - page_flip_data = g_steal_pointer (&retry_page_flip_data->page_flip_data); - - meta_topic (META_DEBUG_KMS, - "[simple] Discarding page flip retry for CRTC %u (%s)", - meta_kms_crtc_get_id ( - meta_kms_page_flip_data_get_crtc (page_flip_data)), - meta_kms_impl_device_get_path ( - meta_kms_page_flip_data_get_impl_device (page_flip_data))); - - dispose_page_flip_data (page_flip_data, impl_device); - retry_page_flip_data_free (retry_page_flip_data); - } - g_clear_pointer (&impl_device_simple->pending_page_flip_retries, g_list_free); - - g_clear_pointer (&impl_device_simple->retry_page_flips_source, - g_source_destroy); -} - -static void -meta_kms_impl_device_simple_prepare_shutdown (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - - g_list_foreach (impl_device_simple->posted_page_flip_datas, - (GFunc) dispose_page_flip_data, - impl_device); - g_clear_list (&impl_device_simple->posted_page_flip_datas, NULL); -} - -static void -meta_kms_impl_device_simple_finalize (GObject *object) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (object); - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple); - - g_list_free_full (impl_device_simple->pending_page_flip_retries, - (GDestroyNotify) retry_page_flip_data_free); - dispatch_page_flip_datas (&impl_device_simple->postponed_page_flip_datas, - (GFunc) dispose_page_flip_data, - impl_device); - dispatch_page_flip_datas (&impl_device_simple->postponed_mode_set_fallback_datas, - (GFunc) dispose_page_flip_data, - impl_device); - - g_assert (!impl_device_simple->posted_page_flip_datas); - - g_clear_pointer (&impl_device_simple->mode_set_fallback_feedback_source, - g_source_destroy); - g_hash_table_destroy (impl_device_simple->cached_mode_sets); - - G_OBJECT_CLASS (meta_kms_impl_device_simple_parent_class)->finalize (object); -} - -static MetaDeviceFile * -meta_kms_impl_device_simple_open_device_file (MetaKmsImplDevice *impl_device, - const char *path, - GError **error) -{ - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - MetaBackend *backend = meta_kms_get_backend (kms); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - g_autoptr (MetaDeviceFile) device_file = NULL; - - device_file = meta_device_pool_open (device_pool, path, - META_DEVICE_FILE_FLAG_TAKE_CONTROL, - error); - if (!device_file) - return NULL; - - if (!meta_device_file_has_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_SIMPLE)) - { - int fd = meta_device_file_get_fd (device_file); - - g_warn_if_fail (!meta_device_file_has_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_ATOMIC)); - - if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED, - "DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported"); - return NULL; - } - - meta_device_file_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_SIMPLE); - } - - return g_steal_pointer (&device_file); -} - -static gboolean -meta_kms_impl_device_simple_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (initable); - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple); - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - GList *l; - - if (!initable_parent_iface->init (initable, cancellable, error)) - return FALSE; - - if (!meta_kms_impl_device_init_mode_setting (impl_device, error)) - return FALSE; - - impl_device_simple->cached_mode_sets = - g_hash_table_new_full (NULL, - NULL, - NULL, - (GDestroyNotify) cached_mode_set_free); - - for (l = meta_kms_device_get_crtcs (device); l; l = l->next) - { - MetaKmsCrtc *crtc = l->data; - MetaKmsPlane *plane; - - plane = meta_kms_device_get_cursor_plane_for (device, crtc); - if (plane) - continue; - - meta_topic (META_DEBUG_KMS, - "[simple] Adding fake cursor plane for CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - - meta_kms_device_add_fake_plane_in_impl (device, - META_KMS_PLANE_TYPE_CURSOR, - crtc); - } - - g_message ("Added device '%s' (%s) using non-atomic mode setting.", - meta_kms_impl_device_get_path (impl_device), - meta_kms_impl_device_get_driver_name (impl_device)); - - return TRUE; -} - -static void -meta_kms_impl_device_simple_init (MetaKmsImplDeviceSimple *impl_device_simple) -{ -} - -static void -initable_iface_init (GInitableIface *iface) -{ - initable_parent_iface = g_type_interface_peek_parent (iface); - - iface->init = meta_kms_impl_device_simple_initable_init; -} - -static void -meta_kms_impl_device_simple_class_init (MetaKmsImplDeviceSimpleClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaKmsImplDeviceClass *impl_device_class = - META_KMS_IMPL_DEVICE_CLASS (klass); - - object_class->finalize = meta_kms_impl_device_simple_finalize; - - impl_device_class->open_device_file = - meta_kms_impl_device_simple_open_device_file; - impl_device_class->setup_drm_event_context = - meta_kms_impl_device_simple_setup_drm_event_context; - impl_device_class->process_update = - meta_kms_impl_device_simple_process_update; - impl_device_class->handle_page_flip_callback = - meta_kms_impl_device_simple_handle_page_flip_callback; - impl_device_class->discard_pending_page_flips = - meta_kms_impl_device_simple_discard_pending_page_flips; - impl_device_class->prepare_shutdown = - meta_kms_impl_device_simple_prepare_shutdown; -} diff --git a/src/backends/native/meta-kms-impl-device-simple.h b/src/backends/native/meta-kms-impl-device-simple.h deleted file mode 100644 index 7be5f0a83..000000000 --- a/src/backends/native/meta-kms-impl-device-simple.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2018-2020 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. - */ - -#ifndef META_KMS_IMPL_DEVICE_SIMPLE_H -#define META_KMS_IMPL_DEVICE_SIMPLE_H - -#include "backends/native/meta-kms-impl-device.h" - -#define META_TYPE_KMS_IMPL_DEVICE_SIMPLE (meta_kms_impl_device_simple_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsImplDeviceSimple, meta_kms_impl_device_simple, - META, KMS_IMPL_DEVICE_SIMPLE, MetaKmsImplDevice) - -#endif /* META_KMS_IMPL_DEVICE_SIMPLE_H */ diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c deleted file mode 100644 index e08e672e5..000000000 --- a/src/backends/native/meta-kms-impl-device.c +++ /dev/null @@ -1,1070 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-impl-device.h" - -#include <errno.h> -#include <xf86drm.h> - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-kms-connector-private.h" -#include "backends/native/meta-kms-connector.h" -#include "backends/native/meta-kms-crtc-private.h" -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-impl.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-page-flip-private.h" -#include "backends/native/meta-kms-plane-private.h" -#include "backends/native/meta-kms-plane.h" -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-update-private.h" - -#include "meta-default-modes.h" -#include "meta-private-enum-types.h" - -enum -{ - PROP_0, - - PROP_DEVICE, - PROP_IMPL, - PROP_PATH, - PROP_FLAGS, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef struct _MetaKmsImplDevicePrivate -{ - MetaKmsDevice *device; - MetaKmsImpl *impl; - - int fd_hold_count; - MetaDeviceFile *device_file; - GSource *fd_source; - char *path; - MetaKmsDeviceFlag flags; - gboolean has_latched_fd_hold; - - char *driver_name; - char *driver_description; - - GList *crtcs; - GList *connectors; - GList *planes; - - MetaKmsDeviceCaps caps; - - GList *fallback_modes; -} MetaKmsImplDevicePrivate; - -static void -initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDevice, meta_kms_impl_device, - G_TYPE_OBJECT, - G_ADD_PRIVATE (MetaKmsImplDevice) - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -G_DEFINE_QUARK (-meta-kms-error-quark, meta_kms_error) - -MetaKmsDevice * -meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->device; -} - -GList * -meta_kms_impl_device_copy_connectors (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return g_list_copy (priv->connectors); -} - -GList * -meta_kms_impl_device_copy_crtcs (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return g_list_copy (priv->crtcs); -} - -GList * -meta_kms_impl_device_copy_planes (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return g_list_copy (priv->planes); -} - -GList * -meta_kms_impl_device_peek_connectors (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->connectors; -} - -GList * -meta_kms_impl_device_peek_crtcs (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->crtcs; -} - -GList * -meta_kms_impl_device_peek_planes (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->planes; -} - -const MetaKmsDeviceCaps * -meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return &priv->caps; -} - -GList * -meta_kms_impl_device_copy_fallback_modes (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return g_list_copy (priv->fallback_modes); -} - -const char * -meta_kms_impl_device_get_driver_name (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->driver_name; -} - -const char * -meta_kms_impl_device_get_driver_description (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->driver_description; -} - -const char * -meta_kms_impl_device_get_path (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->path; -} - -gboolean -meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device, - GError **error) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - int fd; - - drmEventContext drm_event_context; - - meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); - - drm_event_context = (drmEventContext) { 0 }; - klass->setup_drm_event_context (impl_device, &drm_event_context); - - fd = meta_device_file_get_fd (priv->device_file); - - while (TRUE) - { - if (drmHandleEvent (fd, &drm_event_context) != 0) - { - struct pollfd pfd; - int ret; - - if (errno != EAGAIN) - { - g_set_error_literal (error, G_IO_ERROR, - g_io_error_from_errno (errno), - strerror (errno)); - return FALSE; - } - - pfd.fd = fd; - pfd.events = POLL_IN | POLL_ERR; - do - { - ret = poll (&pfd, 1, -1); - } - while (ret == -1 && errno == EINTR); - } - else - { - break; - } - } - - return TRUE; -} - -static gpointer -kms_event_dispatch_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - MetaKmsImplDevice *impl_device = user_data; - gboolean ret; - - ret = meta_kms_impl_device_dispatch (impl_device, error); - return GINT_TO_POINTER (ret); -} - -drmModePropertyPtr -meta_kms_impl_device_find_property (MetaKmsImplDevice *impl_device, - drmModeObjectProperties *props, - const char *prop_name, - int *out_idx) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int fd; - unsigned int i; - - meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); - - fd = meta_device_file_get_fd (priv->device_file); - - for (i = 0; i < props->count_props; i++) - { - drmModePropertyPtr prop; - - prop = drmModeGetProperty (fd, props->props[i]); - if (!prop) - continue; - - if (strcmp (prop->name, prop_name) == 0) - { - *out_idx = i; - return prop; - } - - drmModeFreeProperty (prop); - } - - return NULL; -} - -static void -init_caps (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int fd; - uint64_t cursor_width, cursor_height; - uint64_t prefer_shadow; - uint64_t uses_monotonic_clock; - - fd = meta_device_file_get_fd (priv->device_file); - if (drmGetCap (fd, DRM_CAP_CURSOR_WIDTH, &cursor_width) == 0 && - drmGetCap (fd, DRM_CAP_CURSOR_HEIGHT, &cursor_height) == 0) - { - priv->caps.has_cursor_size = TRUE; - priv->caps.cursor_width = cursor_width; - priv->caps.cursor_height = cursor_height; - } - - if (drmGetCap (fd, DRM_CAP_DUMB_PREFER_SHADOW, &prefer_shadow) == 0) - { - if (prefer_shadow) - g_message ("Device '%s' prefers shadow buffer", priv->path); - - priv->caps.prefers_shadow_buffer = prefer_shadow; - } - - if (drmGetCap (fd, DRM_CAP_TIMESTAMP_MONOTONIC, &uses_monotonic_clock) == 0) - { - priv->caps.uses_monotonic_clock = uses_monotonic_clock; - } -} - -static void -init_crtcs (MetaKmsImplDevice *impl_device, - drmModeRes *drm_resources) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int idx; - int fd; - - fd = meta_device_file_get_fd (priv->device_file); - - for (idx = 0; idx < drm_resources->count_crtcs; idx++) - { - uint32_t crtc_id; - drmModeCrtc *drm_crtc; - MetaKmsCrtc *crtc; - g_autoptr (GError) error = NULL; - - crtc_id = drm_resources->crtcs[idx]; - drm_crtc = drmModeGetCrtc (fd, crtc_id); - if (!drm_crtc) - { - g_warning ("Failed to get CRTC %u info on '%s': %s", - crtc_id, priv->path, error->message); - continue; - } - - crtc = meta_kms_crtc_new (impl_device, drm_crtc, idx, &error); - - drmModeFreeCrtc (drm_crtc); - - if (!crtc) - { - g_warning ("Failed to create CRTC for %u on '%s': %s", - crtc_id, priv->path, error->message); - continue; - } - - priv->crtcs = g_list_prepend (priv->crtcs, crtc); - } - priv->crtcs = g_list_reverse (priv->crtcs); -} - -static MetaKmsConnector * -find_existing_connector (MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - GList *l; - - for (l = priv->connectors; l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - if (meta_kms_connector_is_same_as (connector, drm_connector)) - return connector; - } - - return NULL; -} - -static void -update_connectors (MetaKmsImplDevice *impl_device, - drmModeRes *drm_resources) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - GList *connectors = NULL; - unsigned int i; - int fd; - - fd = meta_device_file_get_fd (priv->device_file); - - for (i = 0; i < drm_resources->count_connectors; i++) - { - drmModeConnector *drm_connector; - MetaKmsConnector *connector; - - drm_connector = drmModeGetConnector (fd, drm_resources->connectors[i]); - if (!drm_connector) - continue; - - connector = find_existing_connector (impl_device, drm_connector); - if (connector) - connector = g_object_ref (connector); - else - connector = meta_kms_connector_new (impl_device, drm_connector, - drm_resources); - drmModeFreeConnector (drm_connector); - - connectors = g_list_prepend (connectors, connector); - } - - g_list_free_full (priv->connectors, g_object_unref); - priv->connectors = g_list_reverse (connectors); -} - -static MetaKmsPlaneType -get_plane_type (MetaKmsImplDevice *impl_device, - drmModeObjectProperties *props) -{ - drmModePropertyPtr prop; - int idx; - - prop = meta_kms_impl_device_find_property (impl_device, props, "type", &idx); - if (!prop) - return FALSE; - drmModeFreeProperty (prop); - - switch (props->prop_values[idx]) - { - case DRM_PLANE_TYPE_PRIMARY: - return META_KMS_PLANE_TYPE_PRIMARY; - case DRM_PLANE_TYPE_CURSOR: - return META_KMS_PLANE_TYPE_CURSOR; - case DRM_PLANE_TYPE_OVERLAY: - return META_KMS_PLANE_TYPE_OVERLAY; - default: - g_warning ("Unhandled plane type %" G_GUINT64_FORMAT, - props->prop_values[idx]); - return -1; - } -} - -MetaKmsPlane * -meta_kms_impl_device_add_fake_plane (MetaKmsImplDevice *impl_device, - MetaKmsPlaneType plane_type, - MetaKmsCrtc *crtc) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaKmsPlane *plane; - - plane = meta_kms_plane_new_fake (plane_type, crtc); - priv->planes = g_list_append (priv->planes, plane); - - return plane; -} - -static MetaKmsProp * -find_prop (MetaKmsProp *props, - int n_props, - const char *name) -{ - int i; - - for (i = 0; i < n_props; i++) - { - MetaKmsProp *prop = &props[i]; - - g_warn_if_fail (prop->name); - - if (g_strcmp0 (prop->name, name) == 0) - return prop; - } - - return NULL; -} - -void -meta_kms_impl_device_init_prop_table (MetaKmsImplDevice *impl_device, - uint32_t *drm_props, - uint64_t *drm_prop_values, - int n_drm_props, - MetaKmsProp *props, - int n_props, - gpointer user_data) -{ - int fd; - uint32_t i; - - fd = meta_kms_impl_device_get_fd (impl_device); - - for (i = 0; i < n_drm_props; i++) - { - drmModePropertyRes *drm_prop; - MetaKmsProp *prop; - - drm_prop = drmModeGetProperty (fd, drm_props[i]); - if (!drm_prop) - continue; - - prop = find_prop (props, n_props, drm_prop->name); - if (!prop) - { - drmModeFreeProperty (drm_prop); - continue; - } - - if (!(drm_prop->flags & prop->type)) - { - g_warning ("DRM property '%s' (%u) had unexpected flags (0x%x), " - "ignoring", - drm_prop->name, drm_props[i], drm_prop->flags); - drmModeFreeProperty (drm_prop); - continue; - } - - prop->prop_id = drm_props[i]; - - if (prop->parse) - { - prop->parse (impl_device, prop, - drm_prop, drm_prop_values[i], - user_data); - } - - drmModeFreeProperty (drm_prop); - } -} - -static void -init_planes (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int fd; - drmModePlaneRes *drm_planes; - unsigned int i; - - fd = meta_device_file_get_fd (priv->device_file); - - drm_planes = drmModeGetPlaneResources (fd); - if (!drm_planes) - return; - - for (i = 0; i < drm_planes->count_planes; i++) - { - drmModePlane *drm_plane; - drmModeObjectProperties *props; - - drm_plane = drmModeGetPlane (fd, drm_planes->planes[i]); - if (!drm_plane) - continue; - - props = drmModeObjectGetProperties (fd, - drm_plane->plane_id, - DRM_MODE_OBJECT_PLANE); - if (props) - { - MetaKmsPlaneType plane_type; - - plane_type = get_plane_type (impl_device, props); - if (plane_type != -1) - { - MetaKmsPlane *plane; - - plane = meta_kms_plane_new (plane_type, - impl_device, - drm_plane, props); - - priv->planes = g_list_prepend (priv->planes, plane); - } - } - - g_clear_pointer (&props, drmModeFreeObjectProperties); - drmModeFreePlane (drm_plane); - } - priv->planes = g_list_reverse (priv->planes); -} - -static void -init_fallback_modes (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - GList *modes = NULL; - int i; - - for (i = 0; i < G_N_ELEMENTS (meta_default_landscape_drm_mode_infos); i++) - { - MetaKmsMode *mode; - - mode = meta_kms_mode_new (impl_device, - &meta_default_landscape_drm_mode_infos[i], - META_KMS_MODE_FLAG_FALLBACK_LANDSCAPE); - modes = g_list_prepend (modes, mode); - } - - for (i = 0; i < G_N_ELEMENTS (meta_default_portrait_drm_mode_infos); i++) - { - MetaKmsMode *mode; - - mode = meta_kms_mode_new (impl_device, - &meta_default_portrait_drm_mode_infos[i], - META_KMS_MODE_FLAG_FALLBACK_PORTRAIT); - modes = g_list_prepend (modes, mode); - } - - priv->fallback_modes = g_list_reverse (modes); -} - -static MetaDeviceFile * -meta_kms_impl_device_open_device_file (MetaKmsImplDevice *impl_device, - const char *path, - GError **error) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - - return klass->open_device_file (impl_device, priv->path, error); -} - -static gboolean -ensure_device_file (MetaKmsImplDevice *impl_device, - GError **error) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaDeviceFile *device_file; - - if (priv->device_file) - return TRUE; - - device_file = meta_kms_impl_device_open_device_file (impl_device, - priv->path, - error); - if (!device_file) - return FALSE; - - priv->device_file = device_file; - - if (!(priv->flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING)) - { - priv->fd_source = - meta_kms_register_fd_in_impl (meta_kms_impl_get_kms (priv->impl), - meta_device_file_get_fd (device_file), - kms_event_dispatch_in_impl, - impl_device); - } - - return TRUE; -} - -static void -ensure_latched_fd_hold (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - if (!priv->has_latched_fd_hold) - { - meta_kms_impl_device_hold_fd (impl_device); - priv->has_latched_fd_hold = TRUE; - } -} - -static void -clear_latched_fd_hold (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - if (priv->has_latched_fd_hold) - { - meta_kms_impl_device_unhold_fd (impl_device); - priv->has_latched_fd_hold = FALSE; - } -} - -void -meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - g_autoptr (GError) error = NULL; - int fd; - drmModeRes *drm_resources; - - meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); - - meta_topic (META_DEBUG_KMS, "Updating device state for %s", priv->path); - - if (!ensure_device_file (impl_device, &error)) - { - g_warning ("Failed to reopen '%s': %s", priv->path, error->message); - goto err; - } - - ensure_latched_fd_hold (impl_device); - - fd = meta_device_file_get_fd (priv->device_file); - drm_resources = drmModeGetResources (fd); - if (!drm_resources) - { - meta_topic (META_DEBUG_KMS, "Device '%s' didn't return any resources", - priv->path); - goto err; - } - - update_connectors (impl_device, drm_resources); - - g_list_foreach (priv->crtcs, (GFunc) meta_kms_crtc_update_state, - NULL); - g_list_foreach (priv->connectors, (GFunc) meta_kms_connector_update_state, - drm_resources); - drmModeFreeResources (drm_resources); - - return; - -err: - g_clear_list (&priv->planes, g_object_unref); - g_clear_list (&priv->crtcs, g_object_unref); - g_clear_list (&priv->connectors, g_object_unref); -} - -void -meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - g_list_foreach (priv->crtcs, (GFunc) meta_kms_crtc_predict_state, - update); - g_list_foreach (priv->connectors, (GFunc) meta_kms_connector_predict_state, - update); -} - -void -meta_kms_impl_device_notify_modes_set (MetaKmsImplDevice *impl_device) -{ - clear_latched_fd_hold (impl_device); -} - -int -meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); - - return meta_device_file_get_fd (priv->device_file); -} - -MetaKmsFeedback * -meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) -{ - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - MetaKmsFeedback *feedback; - g_autoptr (GError) error = NULL; - - if (!ensure_device_file (impl_device, &error)) - return meta_kms_feedback_new_failed (NULL, g_steal_pointer (&error)); - - meta_kms_impl_device_hold_fd (impl_device); - feedback = klass->process_update (impl_device, update, flags); - meta_kms_impl_device_unhold_fd (impl_device); - - return feedback; -} - -void -meta_kms_impl_device_handle_page_flip_callback (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data) -{ - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - - klass->handle_page_flip_callback (impl_device, page_flip_data); -} - -void -meta_kms_impl_device_discard_pending_page_flips (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - - klass->discard_pending_page_flips (impl_device); -} - -void -meta_kms_impl_device_hold_fd (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaKms *kms = meta_kms_device_get_kms (priv->device); - - meta_assert_in_kms_impl (kms); - - g_assert (priv->device_file); - - priv->fd_hold_count++; -} - -void -meta_kms_impl_device_unhold_fd (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaKms *kms = meta_kms_device_get_kms (priv->device); - - meta_assert_in_kms_impl (kms); - - g_return_if_fail (priv->fd_hold_count > 0); - - priv->fd_hold_count--; - if (priv->fd_hold_count == 0) - { - g_clear_pointer (&priv->device_file, meta_device_file_release); - - if (priv->fd_source) - { - g_source_destroy (priv->fd_source); - g_clear_pointer (&priv->fd_source, g_source_unref); - } - } -} - -static void -meta_kms_impl_device_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (object); - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - switch (prop_id) - { - case PROP_DEVICE: - g_value_set_object (value, priv->device); - break; - case PROP_IMPL: - g_value_set_object (value, priv->impl); - break; - case PROP_FLAGS: - g_value_set_flags (value, priv->flags); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_kms_impl_device_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (object); - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - switch (prop_id) - { - case PROP_DEVICE: - priv->device = g_value_get_object (value); - break; - case PROP_IMPL: - priv->impl = g_value_get_object (value); - break; - case PROP_PATH: - priv->path = g_value_dup_string (value); - break; - case PROP_FLAGS: - priv->flags = g_value_get_flags (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_kms_impl_device_finalize (GObject *object) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (object); - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - meta_kms_impl_remove_impl_device (priv->impl, impl_device); - - g_list_free_full (priv->planes, g_object_unref); - g_list_free_full (priv->crtcs, g_object_unref); - g_list_free_full (priv->connectors, g_object_unref); - g_list_free_full (priv->fallback_modes, - (GDestroyNotify) meta_kms_mode_free); - - clear_latched_fd_hold (impl_device); - g_warn_if_fail (!priv->device_file); - - g_free (priv->driver_name); - g_free (priv->driver_description); - g_free (priv->path); - - G_OBJECT_CLASS (meta_kms_impl_device_parent_class)->finalize (object); -} - -gboolean -meta_kms_impl_device_init_mode_setting (MetaKmsImplDevice *impl_device, - GError **error) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int fd; - drmModeRes *drm_resources; - - fd = meta_device_file_get_fd (priv->device_file); - - drm_resources = drmModeGetResources (fd); - if (!drm_resources) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to activate universal planes: %s", - g_strerror (errno)); - return FALSE; - } - - init_caps (impl_device); - - init_crtcs (impl_device, drm_resources); - init_planes (impl_device); - - init_fallback_modes (impl_device); - - update_connectors (impl_device, drm_resources); - - drmModeFreeResources (drm_resources); - - return TRUE; -} - -void -meta_kms_impl_device_prepare_shutdown (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - - if (klass->prepare_shutdown) - klass->prepare_shutdown (impl_device); -} - -static gboolean -get_driver_info (int fd, - char **name, - char **description) -{ - drmVersion *drm_version; - - drm_version = drmGetVersion (fd); - if (!drm_version) - return FALSE; - - *name = g_strndup (drm_version->name, - drm_version->name_len); - *description = g_strndup (drm_version->desc, - drm_version->desc_len); - drmFreeVersion (drm_version); - - return TRUE; -} - -static gboolean -meta_kms_impl_device_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable); - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int fd; - - if (!ensure_device_file (impl_device, error)) - return FALSE; - - ensure_latched_fd_hold (impl_device); - - g_clear_pointer (&priv->path, g_free); - priv->path = g_strdup (meta_device_file_get_path (priv->device_file)); - - fd = meta_device_file_get_fd (priv->device_file); - if (!get_driver_info (fd, &priv->driver_name, &priv->driver_description)) - { - priv->driver_name = g_strdup ("unknown"); - priv->driver_description = g_strdup ("Unknown"); - } - - return TRUE; -} - -static void -meta_kms_impl_device_init (MetaKmsImplDevice *impl_device) -{ -} - -static void -initable_iface_init (GInitableIface *iface) -{ - iface->init = meta_kms_impl_device_initable_init; -} - -static void -meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_kms_impl_device_get_property; - object_class->set_property = meta_kms_impl_device_set_property; - object_class->finalize = meta_kms_impl_device_finalize; - - obj_props[PROP_DEVICE] = - g_param_spec_object ("device", - "device", - "MetaKmsDevice", - META_TYPE_KMS_DEVICE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_IMPL] = - g_param_spec_object ("impl", - "impl", - "MetaKmsImpl", - META_TYPE_KMS_IMPL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_PATH] = - g_param_spec_string ("path", - "path", - "Device path", - NULL, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_FLAGS] = - g_param_spec_flags ("flags", - "flags", - "KMS impl device flags", - META_TYPE_KMS_DEVICE_FLAG, - META_KMS_DEVICE_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h deleted file mode 100644 index e77024ecd..000000000 --- a/src/backends/native/meta-kms-impl-device.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_IMPL_DEVICE_H -#define META_KMS_IMPL_DEVICE_H - -#include <glib-object.h> -#include <stdint.h> -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-page-flip-private.h" -#include "backends/native/meta-kms-types.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms.h" - -typedef struct _MetaKmsDeviceCaps -{ - gboolean has_cursor_size; - uint64_t cursor_width; - uint64_t cursor_height; - - gboolean prefers_shadow_buffer; - gboolean uses_monotonic_clock; -} MetaKmsDeviceCaps; - -typedef struct _MetaKmsProp MetaKmsProp; - -struct _MetaKmsProp -{ - const char *name; - uint32_t type; - MetaKmsPropType internal_type; - void (* parse) (MetaKmsImplDevice *impl_device, - MetaKmsProp *prop, - drmModePropertyPtr drm_prop, - uint64_t value, - gpointer user_data); - - uint32_t prop_id; -}; - -#define META_TYPE_KMS_IMPL_DEVICE (meta_kms_impl_device_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaKmsImplDevice, meta_kms_impl_device, - META, KMS_IMPL_DEVICE, - GObject) - -struct _MetaKmsImplDeviceClass -{ - GObjectClass parent_class; - - MetaDeviceFile * (* open_device_file) (MetaKmsImplDevice *impl_device, - const char *path, - GError **error); - void (* setup_drm_event_context) (MetaKmsImplDevice *impl_device, - drmEventContext *drm_event_context); - MetaKmsFeedback * (* process_update) (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags); - void (* handle_page_flip_callback) (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data); - void (* discard_pending_page_flips) (MetaKmsImplDevice *impl_device); - void (* prepare_shutdown) (MetaKmsImplDevice *impl_device); -}; - -enum -{ - META_KMS_ERROR_USER_INHIBITED, - META_KMS_ERROR_DENY_LISTED, - META_KMS_ERROR_NOT_SUPPORTED, -}; - -enum -{ - META_KMS_DEVICE_FILE_TAG_ATOMIC = 1 << 0, - META_KMS_DEVICE_FILE_TAG_SIMPLE = 1 << 1, -}; - -#define META_KMS_ERROR meta_kms_error_quark () -GQuark meta_kms_error_quark (void); - -MetaKmsDevice * meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_copy_connectors (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_copy_crtcs (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_copy_planes (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_peek_connectors (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_peek_crtcs (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_peek_planes (MetaKmsImplDevice *impl_device); - -const MetaKmsDeviceCaps * meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_copy_fallback_modes (MetaKmsImplDevice *impl_device); - -const char * meta_kms_impl_device_get_driver_name (MetaKmsImplDevice *impl_device); - -const char * meta_kms_impl_device_get_driver_description (MetaKmsImplDevice *impl_device); - -const char * meta_kms_impl_device_get_path (MetaKmsImplDevice *impl_device); - -gboolean meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device, - GError **error); - -drmModePropertyPtr meta_kms_impl_device_find_property (MetaKmsImplDevice *impl_device, - drmModeObjectProperties *props, - const char *prop_name, - int *idx); - -int meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device); - -void meta_kms_impl_device_hold_fd (MetaKmsImplDevice *impl_device); - -void meta_kms_impl_device_unhold_fd (MetaKmsImplDevice *impl_device); - -void meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device); - -void meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update); - -void meta_kms_impl_device_notify_modes_set (MetaKmsImplDevice *impl_device); - -MetaKmsPlane * meta_kms_impl_device_add_fake_plane (MetaKmsImplDevice *impl_device, - MetaKmsPlaneType plane_type, - MetaKmsCrtc *crtc); - -void meta_kms_impl_device_init_prop_table (MetaKmsImplDevice *impl_device, - uint32_t *drm_props, - uint64_t *drm_props_values, - int n_drm_props, - MetaKmsProp *props, - int n_props, - gpointer user_data); - -void meta_kms_impl_device_reload_prop_values (MetaKmsImplDevice *impl_device, - uint32_t *drm_props, - uint64_t *drm_prop_values, - int n_drm_props, - gpointer user_data, - ...); - -MetaKmsFeedback * meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags); - -void meta_kms_impl_device_handle_page_flip_callback (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data); - -void meta_kms_impl_device_discard_pending_page_flips (MetaKmsImplDevice *impl_device); - -gboolean meta_kms_impl_device_init_mode_setting (MetaKmsImplDevice *impl_device, - GError **error); - -void meta_kms_impl_device_prepare_shutdown (MetaKmsImplDevice *impl_device); - -#endif /* META_KMS_IMPL_DEVICE_H */ diff --git a/src/backends/native/meta-kms-impl.c b/src/backends/native/meta-kms-impl.c deleted file mode 100644 index 0ad76e085..000000000 --- a/src/backends/native/meta-kms-impl.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2018 Red Hat - * Copyright (C) 2019 DisplayLink (UK) Ltd. - * - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-impl.h" - -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-update-private.h" - -enum -{ - PROP_0, - - PROP_KMS, -}; - -struct _MetaKmsImpl -{ - GObject parent; -}; - -typedef struct _MetaKmsImplPrivate -{ - MetaKms *kms; - - GList *impl_devices; -} MetaKmsImplPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaKmsImpl, meta_kms_impl, G_TYPE_OBJECT) - -MetaKms * -meta_kms_impl_get_kms (MetaKmsImpl *impl) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - return priv->kms; -} - -void -meta_kms_impl_add_impl_device (MetaKmsImpl *impl, - MetaKmsImplDevice *impl_device) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - meta_assert_in_kms_impl (priv->kms); - - priv->impl_devices = g_list_append (priv->impl_devices, impl_device); -} - -void -meta_kms_impl_remove_impl_device (MetaKmsImpl *impl, - MetaKmsImplDevice *impl_device) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - meta_assert_in_kms_impl (priv->kms); - - priv->impl_devices = g_list_remove (priv->impl_devices, impl_device); -} - -MetaKmsFeedback * -meta_kms_impl_process_update (MetaKmsImpl *impl, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - MetaKmsDevice *device; - MetaKmsImplDevice *impl_device; - - meta_assert_in_kms_impl (priv->kms); - - device = meta_kms_update_get_device (update); - impl_device = meta_kms_device_get_impl_device (device); - - return meta_kms_impl_device_process_update (impl_device, update, flags); -} - -void -meta_kms_impl_discard_pending_page_flips (MetaKmsImpl *impl) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - g_list_foreach (priv->impl_devices, - (GFunc) meta_kms_impl_device_discard_pending_page_flips, - NULL); -} - -void -meta_kms_impl_prepare_shutdown (MetaKmsImpl *impl) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - GList *l; - - for (l = priv->impl_devices; l; l = l->next) - { - MetaKmsImplDevice *impl_device = l->data; - - meta_kms_impl_device_discard_pending_page_flips (impl_device); - meta_kms_impl_device_prepare_shutdown (impl_device); - } -} - -void -meta_kms_impl_notify_modes_set (MetaKmsImpl *impl) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - g_list_foreach (priv->impl_devices, - (GFunc) meta_kms_impl_device_notify_modes_set, - NULL); -} - -MetaKmsImpl * -meta_kms_impl_new (MetaKms *kms) -{ - return g_object_new (META_TYPE_KMS_IMPL, - "kms", kms, - NULL); -} - -static void -meta_kms_impl_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaKmsImpl *impl = META_KMS_IMPL (object); - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - switch (prop_id) - { - case PROP_KMS: - priv->kms = g_value_get_object (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_kms_impl_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaKmsImpl *impl = META_KMS_IMPL (object); - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - switch (prop_id) - { - case PROP_KMS: - g_value_set_object (value, priv->kms); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_kms_impl_init (MetaKmsImpl *kms_impl) -{ -} - -static void -meta_kms_impl_class_init (MetaKmsImplClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GParamSpec *pspec; - - object_class->set_property = meta_kms_impl_set_property; - object_class->get_property = meta_kms_impl_get_property; - - pspec = g_param_spec_object ("kms", - "kms", - "MetaKms", - META_TYPE_KMS, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS | - G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, - PROP_KMS, - pspec); -} diff --git a/src/backends/native/meta-kms-impl.h b/src/backends/native/meta-kms-impl.h deleted file mode 100644 index 58f03f81a..000000000 --- a/src/backends/native/meta-kms-impl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2018 Red Hat - * Copyright (C) 2019 DisplayLink (UK) Ltd. - * - * 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. - */ - -#ifndef META_KMS_IMPL_H -#define META_KMS_IMPL_H - -#include "backends/native/meta-kms-impl-device.h" -#include "backends/native/meta-kms-page-flip-private.h" -#include "backends/native/meta-kms.h" - -#define META_TYPE_KMS_IMPL (meta_kms_impl_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsImpl, meta_kms_impl, - META, KMS_IMPL, GObject) - -MetaKms * meta_kms_impl_get_kms (MetaKmsImpl *impl); - -MetaKmsFeedback * meta_kms_impl_process_update (MetaKmsImpl *impl, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags); - -void meta_kms_impl_add_impl_device (MetaKmsImpl *impl, - MetaKmsImplDevice *impl_device); - -void meta_kms_impl_remove_impl_device (MetaKmsImpl *impl, - MetaKmsImplDevice *impl_device); - -void meta_kms_impl_discard_pending_page_flips (MetaKmsImpl *impl); - -void meta_kms_impl_prepare_shutdown (MetaKmsImpl *impl); - -void meta_kms_impl_notify_modes_set (MetaKmsImpl *impl); - -MetaKmsImpl * meta_kms_impl_new (MetaKms *kms); - -#endif /* META_KMS_IMPL_H */ diff --git a/src/backends/native/meta-kms-mode-private.h b/src/backends/native/meta-kms-mode-private.h deleted file mode 100644 index ded03c52e..000000000 --- a/src/backends/native/meta-kms-mode-private.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ - -#ifndef META_KMS_MODE_PRIVATE_H -#define META_KMS_MODE_PRIVATE_H - -#include "backends/native/meta-kms-mode.h" - -uint32_t meta_kms_mode_create_blob_id (MetaKmsMode *mode, - GError **error); - -void meta_kms_mode_free (MetaKmsMode *mode); - -MetaKmsMode * meta_kms_mode_new (MetaKmsImplDevice *impl_device, - const drmModeModeInfo *drm_mode, - MetaKmsModeFlag flags); - -#endif /* META_KMS_MODE_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-mode.c b/src/backends/native/meta-kms-mode.c deleted file mode 100644 index 7094cd0da..000000000 --- a/src/backends/native/meta-kms-mode.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-mode-private.h" - -#include "backends/native/meta-kms-impl-device.h" - -struct _MetaKmsMode -{ - MetaKmsImplDevice *impl_device; - MetaKmsModeFlag flags; - drmModeModeInfo drm_mode; -}; - -uint32_t -meta_kms_mode_create_blob_id (MetaKmsMode *mode, - GError **error) -{ - int fd; - int ret; - uint32_t blob_id; - - fd = meta_kms_impl_device_get_fd (mode->impl_device); - - ret = drmModeCreatePropertyBlob (fd, - &mode->drm_mode, - sizeof (mode->drm_mode), - &blob_id); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeCreatePropertyBlob: %s", - g_strerror (-ret)); - return 0; - } - - return blob_id; -} - -const char * -meta_kms_mode_get_name (MetaKmsMode *mode) -{ - return mode->drm_mode.name; -} - -MetaKmsModeFlag -meta_kms_mode_get_flags (MetaKmsMode *mode) -{ - return mode->flags; -} - -const drmModeModeInfo * -meta_kms_mode_get_drm_mode (MetaKmsMode *mode) -{ - return &mode->drm_mode; -} - -static gboolean -meta_drm_mode_equal (const drmModeModeInfo *one, - const drmModeModeInfo *two) -{ - return (one->clock == two->clock && - one->hdisplay == two->hdisplay && - one->hsync_start == two->hsync_start && - one->hsync_end == two->hsync_end && - one->htotal == two->htotal && - one->hskew == two->hskew && - one->vdisplay == two->vdisplay && - one->vsync_start == two->vsync_start && - one->vsync_end == two->vsync_end && - one->vtotal == two->vtotal && - one->vscan == two->vscan && - one->vrefresh == two->vrefresh && - one->flags == two->flags && - one->type == two->type && - strncmp (one->name, two->name, DRM_DISPLAY_MODE_LEN) == 0); -} - -gboolean -meta_kms_mode_equal (MetaKmsMode *mode, - MetaKmsMode *other_mode) -{ - return meta_drm_mode_equal (&mode->drm_mode, &other_mode->drm_mode); -} - -unsigned int -meta_kms_mode_hash (MetaKmsMode *mode) -{ - const drmModeModeInfo *drm_mode = &mode->drm_mode; - unsigned int hash = 0; - - /* - * We don't include the name in the hash because it's generally - * derived from the other fields (hdisplay, vdisplay and flags) - */ - - hash ^= drm_mode->clock; - hash ^= drm_mode->hdisplay ^ drm_mode->hsync_start ^ drm_mode->hsync_end; - hash ^= drm_mode->vdisplay ^ drm_mode->vsync_start ^ drm_mode->vsync_end; - hash ^= drm_mode->vrefresh; - hash ^= drm_mode->flags ^ drm_mode->type; - - return hash; -} - -void -meta_kms_mode_free (MetaKmsMode *mode) -{ - g_free (mode); -} - -MetaKmsMode * -meta_kms_mode_new (MetaKmsImplDevice *impl_device, - const drmModeModeInfo *drm_mode, - MetaKmsModeFlag flags) -{ - MetaKmsMode *mode; - - mode = g_new0 (MetaKmsMode, 1); - mode->impl_device = impl_device; - mode->flags = flags; - mode->drm_mode = *drm_mode; - - return mode; -} diff --git a/src/backends/native/meta-kms-mode.h b/src/backends/native/meta-kms-mode.h deleted file mode 100644 index 40e844796..000000000 --- a/src/backends/native/meta-kms-mode.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ - -#ifndef META_KMS_MODE_H -#define META_KMS_MODE_H - -#include <glib.h> -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "backends/native/meta-kms-types.h" - -typedef enum _MetaKmsModeFlag -{ - META_KMS_MODE_FLAG_NONE = 0, - META_KMS_MODE_FLAG_FALLBACK_LANDSCAPE = 1 << 0, - META_KMS_MODE_FLAG_FALLBACK_PORTRAIT = 1 << 1, -} MetaKmsModeFlag; - -const char * meta_kms_mode_get_name (MetaKmsMode *mode); - -MetaKmsModeFlag meta_kms_mode_get_flags (MetaKmsMode *mode); - -const drmModeModeInfo * meta_kms_mode_get_drm_mode (MetaKmsMode *mode); - -gboolean meta_kms_mode_equal (MetaKmsMode *mode, - MetaKmsMode *other_mode); - -unsigned int meta_kms_mode_hash (MetaKmsMode *mode); - -#endif /* META_KMS_MODE_H */ diff --git a/src/backends/native/meta-kms-page-flip-private.h b/src/backends/native/meta-kms-page-flip-private.h deleted file mode 100644 index b23272ad9..000000000 --- a/src/backends/native/meta-kms-page-flip-private.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_PAGE_FLIP_H -#define META_KMS_PAGE_FLIP_H - -#include <glib.h> - -#include "backends/native/meta-kms-types.h" - -typedef struct _MetaKmsPageFlipData MetaKmsPageFlipData; - -typedef void (* MetaPageFlipDataFeedbackFunc) (MetaKmsPageFlipData *page_flip_data); - -MetaKmsPageFlipData * meta_kms_page_flip_data_new (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *crtc); - -MetaKmsPageFlipData * meta_kms_page_flip_data_ref (MetaKmsPageFlipData *page_flip_data); - -void meta_kms_page_flip_data_unref (MetaKmsPageFlipData *page_flip_data); - -void meta_kms_page_flip_data_add_listener (MetaKmsPageFlipData *page_flip_data, - const MetaKmsPageFlipListenerVtable *vtable, - MetaKmsPageFlipListenerFlag flags, - gpointer user_data, - GDestroyNotify destroy_notify); - -MetaKmsImplDevice * meta_kms_page_flip_data_get_impl_device (MetaKmsPageFlipData *page_flip_data); - -MetaKmsCrtc * meta_kms_page_flip_data_get_crtc (MetaKmsPageFlipData *page_flip_data); - -void meta_kms_page_flip_data_set_timings_in_impl (MetaKmsPageFlipData *page_flip_data, - unsigned int sequence, - unsigned int sec, - unsigned int usec); - -void meta_kms_page_flip_data_flipped_in_impl (MetaKmsPageFlipData *page_flip_data); - -void meta_kms_page_flip_data_mode_set_fallback_in_impl (MetaKmsPageFlipData *page_flip_data); - -void meta_kms_page_flip_data_discard_in_impl (MetaKmsPageFlipData *page_flip_data, - const GError *error); - -void meta_kms_page_flip_data_take_error (MetaKmsPageFlipData *page_flip_data, - GError *error); - -void meta_kms_page_flip_data_make_symbolic (MetaKmsPageFlipData *page_flip_data); - -#endif /* META_KMS_PAGE_FLIP_H */ diff --git a/src/backends/native/meta-kms-page-flip.c b/src/backends/native/meta-kms-page-flip.c deleted file mode 100644 index 817f4e7c8..000000000 --- a/src/backends/native/meta-kms-page-flip.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-page-flip-private.h" - -#include "backends/native/meta-kms-impl.h" -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-update.h" - -typedef struct _MetaKmsPageFlipClosure -{ - const MetaKmsPageFlipListenerVtable *vtable; - MetaKmsPageFlipListenerFlag flags; - gpointer user_data; - GDestroyNotify destroy_notify; -} MetaKmsPageFlipClosure; - -struct _MetaKmsPageFlipData -{ - gatomicrefcount ref_count; - - MetaKmsImplDevice *impl_device; - MetaKmsCrtc *crtc; - - GList *closures; - - unsigned int sequence; - unsigned int sec; - unsigned int usec; - - gboolean is_symbolic; - - GError *error; -}; - -static MetaKmsPageFlipClosure * -meta_kms_page_flip_closure_new (const MetaKmsPageFlipListenerVtable *vtable, - MetaKmsPageFlipListenerFlag flags, - gpointer user_data, - GDestroyNotify destroy_notify) -{ - MetaKmsPageFlipClosure *closure; - - closure = g_new0 (MetaKmsPageFlipClosure, 1); - *closure = (MetaKmsPageFlipClosure) { - .vtable = vtable, - .flags = flags, - .user_data = user_data, - .destroy_notify = destroy_notify, - }; - - return closure; -} - -static void -meta_kms_page_flip_closure_free (MetaKmsPageFlipClosure *closure) -{ - g_clear_pointer (&closure->user_data, closure->destroy_notify); - g_free (closure); -} - -MetaKmsPageFlipData * -meta_kms_page_flip_data_new (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *crtc) -{ - MetaKmsPageFlipData *page_flip_data; - - page_flip_data = g_new0 (MetaKmsPageFlipData , 1); - *page_flip_data = (MetaKmsPageFlipData) { - .impl_device = impl_device, - .crtc = crtc, - }; - g_atomic_ref_count_init (&page_flip_data->ref_count); - - return page_flip_data; -} - -MetaKmsPageFlipData * -meta_kms_page_flip_data_ref (MetaKmsPageFlipData *page_flip_data) -{ - g_atomic_ref_count_inc (&page_flip_data->ref_count); - - return page_flip_data; -} - -void -meta_kms_page_flip_data_unref (MetaKmsPageFlipData *page_flip_data) -{ - if (g_atomic_ref_count_dec (&page_flip_data->ref_count)) - { - g_list_free_full (page_flip_data->closures, - (GDestroyNotify) meta_kms_page_flip_closure_free); - g_clear_error (&page_flip_data->error); - g_free (page_flip_data); - } -} - -void -meta_kms_page_flip_data_add_listener (MetaKmsPageFlipData *page_flip_data, - const MetaKmsPageFlipListenerVtable *vtable, - MetaKmsPageFlipListenerFlag flags, - gpointer user_data, - GDestroyNotify destroy_notify) -{ - MetaKmsPageFlipClosure *closure; - - closure = meta_kms_page_flip_closure_new (vtable, flags, - user_data, - destroy_notify); - page_flip_data->closures = g_list_append (page_flip_data->closures, closure); -} - -MetaKmsImplDevice * -meta_kms_page_flip_data_get_impl_device (MetaKmsPageFlipData *page_flip_data) -{ - return page_flip_data->impl_device; -} - -MetaKmsCrtc * -meta_kms_page_flip_data_get_crtc (MetaKmsPageFlipData *page_flip_data) -{ - return page_flip_data->crtc; -} - -static void -meta_kms_page_flip_data_flipped (MetaKms *kms, - gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = user_data; - GList *l; - - meta_assert_not_in_kms_impl (kms); - - for (l = page_flip_data->closures; l; l = l->next) - { - MetaKmsPageFlipClosure *closure = l->data; - - if (page_flip_data->is_symbolic) - { - closure->vtable->ready (page_flip_data->crtc, - closure->user_data); - } - else - { - closure->vtable->flipped (page_flip_data->crtc, - page_flip_data->sequence, - page_flip_data->sec, - page_flip_data->usec, - closure->user_data); - } - } -} - -static MetaKms * -meta_kms_from_impl_device (MetaKmsImplDevice *impl_device) -{ - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - - return meta_kms_device_get_kms (device); -} - -void -meta_kms_page_flip_data_set_timings_in_impl (MetaKmsPageFlipData *page_flip_data, - unsigned int sequence, - unsigned int sec, - unsigned int usec) -{ - MetaKms *kms = meta_kms_from_impl_device (page_flip_data->impl_device); - - meta_assert_in_kms_impl (kms); - - page_flip_data->sequence = sequence; - page_flip_data->sec = sec; - page_flip_data->usec = usec; -} - -void -meta_kms_page_flip_data_make_symbolic (MetaKmsPageFlipData *page_flip_data) -{ - page_flip_data->is_symbolic = TRUE; -} - -void -meta_kms_page_flip_data_flipped_in_impl (MetaKmsPageFlipData *page_flip_data) -{ - MetaKms *kms = meta_kms_from_impl_device (page_flip_data->impl_device); - - meta_assert_in_kms_impl (kms); - - meta_kms_queue_callback (kms, - meta_kms_page_flip_data_flipped, - page_flip_data, - (GDestroyNotify) meta_kms_page_flip_data_unref); -} - -static void -meta_kms_page_flip_data_mode_set_fallback (MetaKms *kms, - gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = user_data; - GList *l; - - meta_assert_not_in_kms_impl (kms); - - for (l = page_flip_data->closures; l; l = l->next) - { - MetaKmsPageFlipClosure *closure = l->data; - - closure->vtable->mode_set_fallback (page_flip_data->crtc, - closure->user_data); - } -} - -void -meta_kms_page_flip_data_mode_set_fallback_in_impl (MetaKmsPageFlipData *page_flip_data) -{ - MetaKms *kms = meta_kms_from_impl_device (page_flip_data->impl_device); - - meta_assert_in_kms_impl (kms); - - meta_kms_queue_callback (kms, - meta_kms_page_flip_data_mode_set_fallback, - page_flip_data, - (GDestroyNotify) meta_kms_page_flip_data_unref); -} - -static void -meta_kms_page_flip_data_discard (MetaKms *kms, - gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = user_data; - GList *l; - - meta_assert_not_in_kms_impl (kms); - - for (l = page_flip_data->closures; l; l = l->next) - { - MetaKmsPageFlipClosure *closure = l->data; - - closure->vtable->discarded (page_flip_data->crtc, - closure->user_data, - page_flip_data->error); - } -} - -void -meta_kms_page_flip_data_take_error (MetaKmsPageFlipData *page_flip_data, - GError *error) -{ - g_assert (!page_flip_data->error); - - page_flip_data->error = error; -} - -void -meta_kms_page_flip_data_discard_in_impl (MetaKmsPageFlipData *page_flip_data, - const GError *error) -{ - MetaKms *kms = meta_kms_from_impl_device (page_flip_data->impl_device); - - meta_assert_in_kms_impl (kms); - - if (error) - meta_kms_page_flip_data_take_error (page_flip_data, g_error_copy (error)); - - meta_kms_queue_callback (kms, - meta_kms_page_flip_data_discard, - page_flip_data, - (GDestroyNotify) meta_kms_page_flip_data_unref); -} diff --git a/src/backends/native/meta-kms-plane-private.h b/src/backends/native/meta-kms-plane-private.h deleted file mode 100644 index 92f9cfcc9..000000000 --- a/src/backends/native/meta-kms-plane-private.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2018-2019 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. - */ - -#ifndef META_KMS_PLANE_PRIVATE_H -#define META_KMS_PLANE_PRIVATE_H - -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "backends/native/meta-kms-plane.h" -#include "backends/native/meta-kms-types.h" - -typedef enum _MetaKmsPlaneProp -{ - META_KMS_PLANE_PROP_TYPE = 0, - META_KMS_PLANE_PROP_ROTATION, - META_KMS_PLANE_PROP_IN_FORMATS, - META_KMS_PLANE_PROP_SRC_X, - META_KMS_PLANE_PROP_SRC_Y, - META_KMS_PLANE_PROP_SRC_W, - META_KMS_PLANE_PROP_SRC_H, - META_KMS_PLANE_PROP_CRTC_X, - META_KMS_PLANE_PROP_CRTC_Y, - META_KMS_PLANE_PROP_CRTC_W, - META_KMS_PLANE_PROP_CRTC_H, - META_KMS_PLANE_PROP_FB_ID, - META_KMS_PLANE_PROP_CRTC_ID, - META_KMS_PLANE_N_PROPS -} MetaKmsPlaneProp; - -MetaKmsPlane * meta_kms_plane_new (MetaKmsPlaneType type, - MetaKmsImplDevice *impl_device, - drmModePlane *drm_plane, - drmModeObjectProperties *drm_plane_props); - -MetaKmsPlane * meta_kms_plane_new_fake (MetaKmsPlaneType type, - MetaKmsCrtc *crtc); - -uint32_t meta_kms_plane_get_prop_id (MetaKmsPlane *plane, - MetaKmsPlaneProp prop); - -const char * meta_kms_plane_get_prop_name (MetaKmsPlane *plane, - MetaKmsPlaneProp prop); - -MetaKmsPropType meta_kms_plane_get_prop_internal_type (MetaKmsPlane *plane, - MetaKmsPlaneProp prop); - -#endif /* META_KMS_PLANE_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-plane.c b/src/backends/native/meta-kms-plane.c deleted file mode 100644 index 73fab7d8f..000000000 --- a/src/backends/native/meta-kms-plane.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (C) 2013-2019 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-plane-private.h" - -#include <drm_fourcc.h> -#include <stdio.h> - -#include "backends/meta-monitor-transform.h" -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-impl-device.h" -#include "backends/native/meta-kms-update-private.h" - -typedef struct _MetaKmsPlanePropTable -{ - MetaKmsProp props[META_KMS_PLANE_N_PROPS]; -} MetaKmsPlanePropTable; - -struct _MetaKmsPlane -{ - GObject parent; - - MetaKmsPlaneType type; - gboolean is_fake; - - uint32_t id; - - uint32_t possible_crtcs; - - uint32_t rotation_map[META_MONITOR_N_TRANSFORMS]; - uint32_t all_hw_transforms; - - /* - * primary plane's supported formats and maybe modifiers - * key: GUINT_TO_POINTER (format) - * value: owned GArray* (uint64_t modifier), or NULL - */ - GHashTable *formats_modifiers; - - MetaKmsPlanePropTable prop_table; - - MetaKmsDevice *device; -}; - -G_DEFINE_TYPE (MetaKmsPlane, meta_kms_plane, G_TYPE_OBJECT) - -MetaKmsDevice * -meta_kms_plane_get_device (MetaKmsPlane *plane) -{ - return plane->device; -} - -uint32_t -meta_kms_plane_get_id (MetaKmsPlane *plane) -{ - g_return_val_if_fail (!plane->is_fake, 0); - - return plane->id; -} - -MetaKmsPlaneType -meta_kms_plane_get_plane_type (MetaKmsPlane *plane) -{ - return plane->type; -} - -uint32_t -meta_kms_plane_get_prop_id (MetaKmsPlane *plane, - MetaKmsPlaneProp prop) -{ - return plane->prop_table.props[prop].prop_id; -} - -const char * -meta_kms_plane_get_prop_name (MetaKmsPlane *plane, - MetaKmsPlaneProp prop) -{ - return plane->prop_table.props[prop].name; -} - -MetaKmsPropType -meta_kms_plane_get_prop_internal_type (MetaKmsPlane *plane, - MetaKmsPlaneProp prop) -{ - return plane->prop_table.props[prop].internal_type; -} - -void -meta_kms_plane_update_set_rotation (MetaKmsPlane *plane, - MetaKmsPlaneAssignment *plane_assignment, - MetaMonitorTransform transform) -{ - g_return_if_fail (meta_kms_plane_is_transform_handled (plane, transform)); - - meta_kms_plane_assignment_set_rotation (plane_assignment, - plane->rotation_map[transform]); -} - -gboolean -meta_kms_plane_is_transform_handled (MetaKmsPlane *plane, - MetaMonitorTransform transform) -{ - switch (transform) - { - case META_MONITOR_TRANSFORM_NORMAL: - case META_MONITOR_TRANSFORM_180: - case META_MONITOR_TRANSFORM_FLIPPED: - case META_MONITOR_TRANSFORM_FLIPPED_180: - break; - case META_MONITOR_TRANSFORM_90: - case META_MONITOR_TRANSFORM_270: - case META_MONITOR_TRANSFORM_FLIPPED_90: - case META_MONITOR_TRANSFORM_FLIPPED_270: - /* - * Blacklist these transforms as testing shows that they don't work - * anyway, e.g. due to the wrong buffer modifiers. They might as well be - * less optimal due to the complexity dealing with rotation at scan-out, - * potentially resulting in higher power consumption. - */ - return FALSE; - } - return plane->all_hw_transforms & (1 << transform); -} - -GArray * -meta_kms_plane_get_modifiers_for_format (MetaKmsPlane *plane, - uint32_t format) -{ - return g_hash_table_lookup (plane->formats_modifiers, - GUINT_TO_POINTER (format)); -} - -GArray * -meta_kms_plane_copy_drm_format_list (MetaKmsPlane *plane) -{ - GArray *formats; - GHashTableIter it; - gpointer key; - unsigned int n_formats_modifiers; - - n_formats_modifiers = g_hash_table_size (plane->formats_modifiers); - formats = g_array_sized_new (FALSE, FALSE, - sizeof (uint32_t), - n_formats_modifiers); - g_hash_table_iter_init (&it, plane->formats_modifiers); - while (g_hash_table_iter_next (&it, &key, NULL)) - { - uint32_t drm_format = GPOINTER_TO_UINT (key); - - g_array_append_val (formats, drm_format); - } - - return formats; -} - -gboolean -meta_kms_plane_is_format_supported (MetaKmsPlane *plane, - uint32_t drm_format) -{ - return g_hash_table_lookup_extended (plane->formats_modifiers, - GUINT_TO_POINTER (drm_format), - NULL, NULL); -} - -gboolean -meta_kms_plane_is_usable_with (MetaKmsPlane *plane, - MetaKmsCrtc *crtc) -{ - return !!(plane->possible_crtcs & (1 << meta_kms_crtc_get_idx (crtc))); -} - -static void -parse_rotations (MetaKmsImplDevice *impl_device, - MetaKmsProp *prop, - drmModePropertyPtr drm_prop, - uint64_t drm_prop_value, - gpointer user_data) -{ - MetaKmsPlane *plane = user_data; - int i; - - for (i = 0; i < drm_prop->count_enums; i++) - { - MetaMonitorTransform transform = -1; - - if (strcmp (drm_prop->enums[i].name, "rotate-0") == 0) - transform = META_MONITOR_TRANSFORM_NORMAL; - else if (strcmp (drm_prop->enums[i].name, "rotate-90") == 0) - transform = META_MONITOR_TRANSFORM_90; - else if (strcmp (drm_prop->enums[i].name, "rotate-180") == 0) - transform = META_MONITOR_TRANSFORM_180; - else if (strcmp (drm_prop->enums[i].name, "rotate-270") == 0) - transform = META_MONITOR_TRANSFORM_270; - - if (transform != -1) - { - plane->all_hw_transforms |= 1 << transform; - plane->rotation_map[transform] = 1 << drm_prop->enums[i].value; - } - } -} - -static inline uint32_t * -drm_formats_ptr (struct drm_format_modifier_blob *blob) -{ - return (uint32_t *) (((char *) blob) + blob->formats_offset); -} - -static inline struct drm_format_modifier * -drm_modifiers_ptr (struct drm_format_modifier_blob *blob) -{ - return (struct drm_format_modifier *) (((char *) blob) + - blob->modifiers_offset); -} - -static void -free_modifier_array (GArray *array) -{ - if (!array) - return; - - g_array_free (array, TRUE); -} - -static void -parse_formats (MetaKmsImplDevice *impl_device, - MetaKmsProp *prop, - drmModePropertyPtr drm_prop, - uint64_t drm_prop_value, - gpointer user_data) -{ - MetaKmsPlane *plane = user_data; - uint64_t blob_id; - int fd; - drmModePropertyBlobPtr blob; - struct drm_format_modifier_blob *blob_fmt; - uint32_t *formats; - struct drm_format_modifier *drm_modifiers; - unsigned int fmt_i, mod_i; - - g_return_if_fail (g_hash_table_size (plane->formats_modifiers) == 0); - - blob_id = drm_prop_value; - if (blob_id == 0) - return; - - fd = meta_kms_impl_device_get_fd (impl_device); - blob = drmModeGetPropertyBlob (fd, blob_id); - if (!blob) - return; - - if (blob->length < sizeof (struct drm_format_modifier_blob)) - { - drmModeFreePropertyBlob (blob); - return; - } - - blob_fmt = blob->data; - - formats = drm_formats_ptr (blob_fmt); - drm_modifiers = drm_modifiers_ptr (blob_fmt); - - for (fmt_i = 0; fmt_i < blob_fmt->count_formats; fmt_i++) - { - GArray *modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t)); - - for (mod_i = 0; mod_i < blob_fmt->count_modifiers; mod_i++) - { - struct drm_format_modifier *drm_modifier = &drm_modifiers[mod_i]; - - /* - * The modifier advertisement blob is partitioned into groups of - * 64 formats. - */ - if (fmt_i < drm_modifier->offset || fmt_i > drm_modifier->offset + 63) - continue; - - if (!(drm_modifier->formats & (1 << (fmt_i - drm_modifier->offset)))) - continue; - - g_array_append_val (modifiers, drm_modifier->modifier); - } - - if (modifiers->len == 0) - { - free_modifier_array (modifiers); - modifiers = NULL; - } - - g_hash_table_insert (plane->formats_modifiers, - GUINT_TO_POINTER (formats[fmt_i]), - modifiers); - } - - drmModeFreePropertyBlob (blob); -} - -static void -set_formats_from_array (MetaKmsPlane *plane, - const uint32_t *formats, - size_t n_formats) -{ - size_t i; - - for (i = 0; i < n_formats; i++) - { - g_hash_table_insert (plane->formats_modifiers, - GUINT_TO_POINTER (formats[i]), NULL); - } -} - -/* - * In case the DRM driver does not expose a format list for the - * primary plane (does not support universal planes nor - * IN_FORMATS property), hardcode something that is probably supported. - */ -static const uint32_t drm_default_formats[] = - { - /* The format everything should always support by convention */ - DRM_FORMAT_XRGB8888, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - /* OpenGL GL_RGBA, GL_UNSIGNED_BYTE format, hopefully supported */ - DRM_FORMAT_XBGR8888 -#endif - }; - -static void -init_legacy_formats (MetaKmsPlane *plane, - MetaKmsImplDevice *impl_device, - drmModePlane *drm_plane, - drmModeObjectProperties *drm_plane_props) -{ - if (g_hash_table_size (plane->formats_modifiers) == 0) - { - set_formats_from_array (plane, - drm_plane->formats, - drm_plane->count_formats); - } - - /* final formats fallback to something hardcoded */ - if (g_hash_table_size (plane->formats_modifiers) == 0) - { - set_formats_from_array (plane, - drm_default_formats, - G_N_ELEMENTS (drm_default_formats)); - } -} - -static void -init_properties (MetaKmsPlane *plane, - MetaKmsImplDevice *impl_device, - drmModePlane *drm_plane, - drmModeObjectProperties *drm_plane_props) -{ - MetaKmsPlanePropTable *prop_table = &plane->prop_table; - - *prop_table = (MetaKmsPlanePropTable) { - .props = { - [META_KMS_PLANE_PROP_TYPE] = - { - .name = "type", - .type = DRM_MODE_PROP_ENUM, - }, - [META_KMS_PLANE_PROP_ROTATION] = - { - .name = "rotation", - .type = DRM_MODE_PROP_BITMASK, - .parse = parse_rotations, - }, - [META_KMS_PLANE_PROP_IN_FORMATS] = - { - .name = "IN_FORMATS", - .type = DRM_MODE_PROP_BLOB, - .parse = parse_formats, - }, - [META_KMS_PLANE_PROP_SRC_X] = - { - .name = "SRC_X", - .type = DRM_MODE_PROP_RANGE, - .internal_type = META_KMS_PROP_TYPE_FIXED_16, - }, - [META_KMS_PLANE_PROP_SRC_Y] = - { - .name = "SRC_Y", - .type = DRM_MODE_PROP_RANGE, - .internal_type = META_KMS_PROP_TYPE_FIXED_16, - }, - [META_KMS_PLANE_PROP_SRC_W] = - { - .name = "SRC_W", - .type = DRM_MODE_PROP_RANGE, - .internal_type = META_KMS_PROP_TYPE_FIXED_16, - }, - [META_KMS_PLANE_PROP_SRC_H] = - { - .name = "SRC_H", - .type = DRM_MODE_PROP_RANGE, - .internal_type = META_KMS_PROP_TYPE_FIXED_16, - }, - [META_KMS_PLANE_PROP_CRTC_X] = - { - .name = "CRTC_X", - .type = DRM_MODE_PROP_SIGNED_RANGE, - }, - [META_KMS_PLANE_PROP_CRTC_Y] = - { - .name = "CRTC_Y", - .type = DRM_MODE_PROP_SIGNED_RANGE, - }, - [META_KMS_PLANE_PROP_CRTC_W] = - { - .name = "CRTC_W", - .type = DRM_MODE_PROP_RANGE, - }, - [META_KMS_PLANE_PROP_CRTC_H] = - { - .name = "CRTC_H", - .type = DRM_MODE_PROP_RANGE, - }, - [META_KMS_PLANE_PROP_FB_ID] = - { - .name = "FB_ID", - .type = DRM_MODE_PROP_OBJECT, - }, - [META_KMS_PLANE_PROP_CRTC_ID] = - { - .name = "CRTC_ID", - .type = DRM_MODE_PROP_OBJECT, - }, - } - }; - - meta_kms_impl_device_init_prop_table (impl_device, - drm_plane_props->props, - drm_plane_props->prop_values, - drm_plane_props->count_props, - plane->prop_table.props, - META_KMS_PLANE_N_PROPS, - plane); -} - -MetaKmsPlane * -meta_kms_plane_new (MetaKmsPlaneType type, - MetaKmsImplDevice *impl_device, - drmModePlane *drm_plane, - drmModeObjectProperties *drm_plane_props) -{ - MetaKmsPlane *plane; - - plane = g_object_new (META_TYPE_KMS_PLANE, NULL); - plane->type = type; - plane->id = drm_plane->plane_id; - plane->possible_crtcs = drm_plane->possible_crtcs; - plane->device = meta_kms_impl_device_get_device (impl_device); - - init_properties (plane, impl_device, drm_plane, drm_plane_props); - init_legacy_formats (plane, impl_device, drm_plane, drm_plane_props); - - return plane; -} - -MetaKmsPlane * -meta_kms_plane_new_fake (MetaKmsPlaneType type, - MetaKmsCrtc *crtc) -{ - MetaKmsPlane *plane; - - static const uint32_t fake_plane_drm_formats[] = - { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - /* OpenGL GL_RGBA, GL_UNSIGNED_BYTE format, hopefully supported */ - DRM_FORMAT_XBGR8888, - DRM_FORMAT_ABGR8888 -#endif - }; - - plane = g_object_new (META_TYPE_KMS_PLANE, NULL); - plane->type = type; - plane->is_fake = TRUE; - plane->possible_crtcs = 1 << meta_kms_crtc_get_idx (crtc); - plane->device = meta_kms_crtc_get_device (crtc); - - set_formats_from_array (plane, - fake_plane_drm_formats, - G_N_ELEMENTS (fake_plane_drm_formats)); - - return plane; -} - -static void -meta_kms_plane_finalize (GObject *object) -{ - MetaKmsPlane *plane = META_KMS_PLANE (object); - - g_hash_table_destroy (plane->formats_modifiers); - - G_OBJECT_CLASS (meta_kms_plane_parent_class)->finalize (object); -} - -static void -meta_kms_plane_init (MetaKmsPlane *plane) -{ - plane->formats_modifiers = - g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify) free_modifier_array); -} - -static void -meta_kms_plane_class_init (MetaKmsPlaneClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_kms_plane_finalize; -} diff --git a/src/backends/native/meta-kms-plane.h b/src/backends/native/meta-kms-plane.h deleted file mode 100644 index 941c16680..000000000 --- a/src/backends/native/meta-kms-plane.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -#ifndef META_KMS_PLANE_H -#define META_KMS_PLANE_H - -#include <glib-object.h> -#include <stdint.h> -#include <xf86drmMode.h> - -#include "backends/native/meta-kms-types.h" -#include "backends/meta-monitor-transform.h" - -enum _MetaKmsPlaneType -{ - META_KMS_PLANE_TYPE_PRIMARY, - META_KMS_PLANE_TYPE_CURSOR, - META_KMS_PLANE_TYPE_OVERLAY, -}; - -#define META_TYPE_KMS_PLANE meta_kms_plane_get_type () -G_DECLARE_FINAL_TYPE (MetaKmsPlane, meta_kms_plane, - META, KMS_PLANE, GObject) - -MetaKmsDevice * meta_kms_plane_get_device (MetaKmsPlane *plane); - -uint32_t meta_kms_plane_get_id (MetaKmsPlane *plane); - -MetaKmsPlaneType meta_kms_plane_get_plane_type (MetaKmsPlane *plane); - -gboolean meta_kms_plane_is_transform_handled (MetaKmsPlane *plane, - MetaMonitorTransform transform); - -GArray * meta_kms_plane_get_modifiers_for_format (MetaKmsPlane *plane, - uint32_t format); - -GArray * meta_kms_plane_copy_drm_format_list (MetaKmsPlane *plane); - -gboolean meta_kms_plane_is_format_supported (MetaKmsPlane *plane, - uint32_t format); - -gboolean meta_kms_plane_is_usable_with (MetaKmsPlane *plane, - MetaKmsCrtc *crtc); - -void meta_kms_plane_update_set_rotation (MetaKmsPlane *plane, - MetaKmsPlaneAssignment *plane_assignment, - MetaMonitorTransform transform); - -#endif /* META_KMS_PLANE_H */ diff --git a/src/backends/native/meta-kms-private.h b/src/backends/native/meta-kms-private.h deleted file mode 100644 index 8d0954c72..000000000 --- a/src/backends/native/meta-kms-private.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_PRIVATE_H -#define META_KMS_PRIVATE_H - -#include "backends/native/meta-kms.h" - -#include "backends/native/meta-kms-types.h" - -typedef void (* MetaKmsCallback) (MetaKms *kms, - gpointer user_data); - -typedef gpointer (* MetaKmsImplTaskFunc) (MetaKmsImpl *impl, - gpointer user_data, - GError **error); - -void meta_kms_queue_callback (MetaKms *kms, - MetaKmsCallback callback, - gpointer user_data, - GDestroyNotify user_data_destroy); - -gpointer meta_kms_run_impl_task_sync (MetaKms *kms, - MetaKmsImplTaskFunc func, - gpointer user_data, - GError **error); - -GSource * meta_kms_add_source_in_impl (MetaKms *kms, - GSourceFunc func, - gpointer user_data, - GDestroyNotify user_data_destroy); - -GSource * meta_kms_register_fd_in_impl (MetaKms *kms, - int fd, - MetaKmsImplTaskFunc dispatch, - gpointer user_data); - -gboolean meta_kms_in_impl_task (MetaKms *kms); - -gboolean meta_kms_is_waiting_for_impl_task (MetaKms *kms); - -#define meta_assert_in_kms_impl(kms) \ - g_assert (meta_kms_in_impl_task (kms)) -#define meta_assert_not_in_kms_impl(kms) \ - g_assert (!meta_kms_in_impl_task (kms)) -#define meta_assert_is_waiting_for_kms_impl_task(kms) \ - g_assert (meta_kms_is_waiting_for_impl_task (kms)) - -#endif /* META_KMS_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h deleted file mode 100644 index 5786ff51f..000000000 --- a/src/backends/native/meta-kms-types.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_IMPL_TYPES_H -#define META_KMS_IMPL_TYPES_H - -#include <stdint.h> - -typedef struct _MetaKms MetaKms; -typedef struct _MetaKmsDevice MetaKmsDevice; - -typedef struct _MetaKmsPlane MetaKmsPlane; -typedef struct _MetaKmsCrtc MetaKmsCrtc; -typedef struct _MetaKmsConnector MetaKmsConnector; - -typedef struct _MetaKmsUpdate MetaKmsUpdate; -typedef struct _MetaKmsPlaneAssignment MetaKmsPlaneAssignment; -typedef struct _MetaKmsModeSet MetaKmsModeSet; - -typedef struct _MetaKmsMode MetaKmsMode; - -typedef struct _MetaKmsFeedback MetaKmsFeedback; - -typedef struct _MetaKmsPageFlipListenerVtable MetaKmsPageFlipListenerVtable; -typedef enum _MetaKmsPageFlipListenerFlag MetaKmsPageFlipListenerFlag; - -typedef struct _MetaKmsImpl MetaKmsImpl; -typedef struct _MetaKmsImplDevice MetaKmsImplDevice; - -/* 16:16 fixed point */ -typedef int32_t MetaFixed16; - -typedef struct _MetaFixed16Rectangle -{ - MetaFixed16 x; - MetaFixed16 y; - MetaFixed16 width; - MetaFixed16 height; -} MetaFixed16Rectangle; - -typedef enum _MetaKmsDeviceFlag -{ - META_KMS_DEVICE_FLAG_NONE = 0, - META_KMS_DEVICE_FLAG_BOOT_VGA = 1 << 0, - META_KMS_DEVICE_FLAG_PLATFORM_DEVICE = 1 << 1, - META_KMS_DEVICE_FLAG_DISABLE_MODIFIERS = 1 << 2, - META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY = 1 << 3, - META_KMS_DEVICE_FLAG_NO_MODE_SETTING = 1 << 4, -} MetaKmsDeviceFlag; - -typedef enum _MetaKmsPlaneType MetaKmsPlaneType; - -typedef enum _MetaKmsPropType -{ - META_KMS_PROP_TYPE_RAW = 0, - META_KMS_PROP_TYPE_FIXED_16, -} MetaKmsPropType; - -#endif /* META_KMS_IMPL_TYPES_H */ diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h deleted file mode 100644 index 22491ece2..000000000 --- a/src/backends/native/meta-kms-update-private.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2019 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. - */ - -#ifndef META_KMS_UPDATE_PRIVATE_H -#define META_KMS_UPDATE_PRIVATE_H - -#include <glib.h> -#include <stdint.h> - -#include "backends/native/meta-kms-types.h" -#include "backends/native/meta-kms-update.h" - -typedef struct _MetaKmsFeedback -{ - MetaKmsFeedbackResult result; - - GList *failed_planes; - GError *error; -} MetaKmsFeedback; - -typedef struct _MetaKmsPlaneAssignment -{ - MetaKmsUpdate *update; - MetaKmsCrtc *crtc; - MetaKmsPlane *plane; - MetaDrmBuffer *buffer; - MetaFixed16Rectangle src_rect; - MetaRectangle dst_rect; - MetaKmsAssignPlaneFlag flags; - - uint64_t rotation; - - struct { - gboolean is_valid; - int x; - int y; - } cursor_hotspot; -} MetaKmsPlaneAssignment; - -typedef struct _MetaKmsModeSet -{ - MetaKmsCrtc *crtc; - GList *connectors; - MetaKmsMode *mode; -} MetaKmsModeSet; - -typedef struct _MetaKmsConnectorUpdate -{ - MetaKmsConnector *connector; - - struct { - gboolean has_update; - gboolean is_active; - uint64_t hborder; - uint64_t vborder; - } underscanning; -} MetaKmsConnectorUpdate; - -typedef struct _MetaKmsPageFlipListener -{ - MetaKmsCrtc *crtc; - const MetaKmsPageFlipListenerVtable *vtable; - MetaKmsPageFlipListenerFlag flags; - gpointer user_data; - GDestroyNotify destroy_notify; -} MetaKmsPageFlipListener; - -typedef struct _MetaKmsResultListener -{ - MetaKmsResultListenerFunc func; - gpointer user_data; -} MetaKmsResultListener; - -typedef struct _MetaKmsCustomPageFlip -{ - MetaKmsCustomPageFlipFunc func; - gpointer user_data; -} MetaKmsCustomPageFlip; - -void meta_kms_plane_feedback_free (MetaKmsPlaneFeedback *plane_feedback); - -MetaKmsPlaneFeedback * meta_kms_plane_feedback_new_take_error (MetaKmsPlane *plane, - MetaKmsCrtc *crtc, - GError *error); - -MetaKmsFeedback * meta_kms_feedback_new_passed (GList *failed_planes); - -MetaKmsFeedback * meta_kms_feedback_new_failed (GList *failed_planes, - GError *error); - -void meta_kms_update_lock (MetaKmsUpdate *update); - -void meta_kms_update_unlock (MetaKmsUpdate *update); - -gboolean meta_kms_update_is_locked (MetaKmsUpdate *update); - -uint64_t meta_kms_update_get_sequence_number (MetaKmsUpdate *update); - -MetaKmsDevice * meta_kms_update_get_device (MetaKmsUpdate *update); - -void meta_kms_plane_assignment_set_rotation (MetaKmsPlaneAssignment *plane_assignment, - uint64_t rotation); - -MetaKmsPlaneAssignment * meta_kms_update_get_primary_plane_assignment (MetaKmsUpdate *update, - MetaKmsCrtc *crtc); - -GList * meta_kms_update_get_plane_assignments (MetaKmsUpdate *update); - -GList * meta_kms_update_get_mode_sets (MetaKmsUpdate *update); - -GList * meta_kms_update_get_page_flip_listeners (MetaKmsUpdate *update); - -void meta_kms_update_drop_defunct_page_flip_listeners (MetaKmsUpdate *update); - -GList * meta_kms_update_get_connector_updates (MetaKmsUpdate *update); - -GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update); - -gboolean meta_kms_update_is_power_save (MetaKmsUpdate *update); - -MetaKmsCustomPageFlip * meta_kms_update_take_custom_page_flip_func (MetaKmsUpdate *update); - -void meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update, - MetaKmsPlane *plane); - -GList * meta_kms_update_take_result_listeners (MetaKmsUpdate *update); - -void meta_kms_result_listener_notify (MetaKmsResultListener *listener, - const MetaKmsFeedback *feedback); - -void meta_kms_result_listener_free (MetaKmsResultListener *listener); - -void meta_kms_custom_page_flip_free (MetaKmsCustomPageFlip *custom_page_flip); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsPlaneFeedback, - meta_kms_plane_feedback_free) - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsCustomPageFlip, - meta_kms_custom_page_flip_free) - -#endif /* META_KMS_UPDATE_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c deleted file mode 100644 index be6eaefcc..000000000 --- a/src/backends/native/meta-kms-update.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms-update-private.h" - -#include "backends/meta-display-config-shared.h" -#include "backends/native/meta-kms-connector.h" -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-plane.h" - -struct _MetaKmsUpdate -{ - MetaKmsDevice *device; - - gboolean is_locked; - uint64_t sequence_number; - - gboolean power_save; - - GList *mode_sets; - GList *plane_assignments; - GList *connector_updates; - GList *crtc_gammas; - - MetaKmsCustomPageFlip *custom_page_flip; - - GList *page_flip_listeners; - GList *result_listeners; -}; - -void -meta_kms_plane_feedback_free (MetaKmsPlaneFeedback *plane_feedback) -{ - g_error_free (plane_feedback->error); - g_free (plane_feedback); -} - -MetaKmsPlaneFeedback * -meta_kms_plane_feedback_new_take_error (MetaKmsPlane *plane, - MetaKmsCrtc *crtc, - GError *error) -{ - MetaKmsPlaneFeedback *plane_feedback; - - plane_feedback = g_new0 (MetaKmsPlaneFeedback, 1); - *plane_feedback = (MetaKmsPlaneFeedback) { - .plane = plane, - .crtc = crtc, - .error = error, - }; - - return plane_feedback; -} - -MetaKmsFeedback * -meta_kms_feedback_new_passed (GList *failed_planes) -{ - MetaKmsFeedback *feedback; - - feedback = g_new0 (MetaKmsFeedback, 1); - *feedback = (MetaKmsFeedback) { - .result = META_KMS_FEEDBACK_PASSED, - .failed_planes = failed_planes, - }; - - return feedback; -} - -MetaKmsFeedback * -meta_kms_feedback_new_failed (GList *failed_planes, - GError *error) -{ - MetaKmsFeedback *feedback; - - feedback = g_new0 (MetaKmsFeedback, 1); - *feedback = (MetaKmsFeedback) { - .result = META_KMS_FEEDBACK_FAILED, - .error = error, - .failed_planes = failed_planes, - }; - - return feedback; -} - -void -meta_kms_feedback_free (MetaKmsFeedback *feedback) -{ - g_list_free_full (feedback->failed_planes, - (GDestroyNotify) meta_kms_plane_feedback_free); - g_clear_error (&feedback->error); - g_free (feedback); -} - -MetaKmsFeedbackResult -meta_kms_feedback_get_result (const MetaKmsFeedback *feedback) -{ - return feedback->result; -} - -GList * -meta_kms_feedback_get_failed_planes (const MetaKmsFeedback *feedback) -{ - return feedback->failed_planes; -} - -const GError * -meta_kms_feedback_get_error (const MetaKmsFeedback *feedback) -{ - return feedback->error; -} - -static void -meta_kms_plane_assignment_free (MetaKmsPlaneAssignment *plane_assignment) -{ - g_free (plane_assignment); -} - -static void -meta_kms_mode_set_free (MetaKmsModeSet *mode_set) -{ - g_list_free (mode_set->connectors); - g_free (mode_set); -} - -static void -meta_kms_page_flip_listener_free (MetaKmsPageFlipListener *listener) -{ - g_clear_pointer (&listener->user_data, listener->destroy_notify); - g_free (listener); -} - -static gboolean -drop_plane_assignment (MetaKmsUpdate *update, - MetaKmsPlane *plane, - MetaKmsAssignPlaneFlag *out_flags) -{ - GList *l; - - for (l = update->plane_assignments; l; l = l->next) - { - MetaKmsPlaneAssignment *plane_assignment = l->data; - - if (plane_assignment->plane == plane) - { - update->plane_assignments = - g_list_delete_link (update->plane_assignments, l); - if (out_flags) - *out_flags = plane_assignment->flags; - meta_kms_plane_assignment_free (plane_assignment); - return TRUE; - } - } - - return FALSE; -} - -void -meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update, - MetaKmsPlane *plane) -{ - drop_plane_assignment (update, plane, NULL); -} - -MetaKmsPlaneAssignment * -meta_kms_update_assign_plane (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - MetaKmsPlane *plane, - MetaDrmBuffer *buffer, - MetaFixed16Rectangle src_rect, - MetaRectangle dst_rect, - MetaKmsAssignPlaneFlag flags) -{ - MetaKmsPlaneAssignment *plane_assignment; - MetaKmsAssignPlaneFlag old_flags; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_crtc_get_device (crtc) == update->device); - g_assert (!update->power_save); - g_assert (meta_kms_plane_get_device (plane) == update->device); - g_assert (meta_kms_plane_get_plane_type (plane) != - META_KMS_PLANE_TYPE_PRIMARY || - !(flags & META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL)); - - if (drop_plane_assignment (update, plane, &old_flags)) - { - if (!(old_flags & META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED)) - flags &= ~META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED; - } - - plane_assignment = g_new0 (MetaKmsPlaneAssignment, 1); - *plane_assignment = (MetaKmsPlaneAssignment) { - .update = update, - .crtc = crtc, - .plane = plane, - .buffer = buffer, - .src_rect = src_rect, - .dst_rect = dst_rect, - .flags = flags, - }; - - update->plane_assignments = g_list_prepend (update->plane_assignments, - plane_assignment); - - return plane_assignment; -} - -MetaKmsPlaneAssignment * -meta_kms_update_unassign_plane (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - MetaKmsPlane *plane) -{ - MetaKmsPlaneAssignment *plane_assignment; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_crtc_get_device (crtc) == update->device); - g_assert (meta_kms_plane_get_device (plane) == update->device); - g_assert (!update->power_save); - - plane_assignment = g_new0 (MetaKmsPlaneAssignment, 1); - *plane_assignment = (MetaKmsPlaneAssignment) { - .update = update, - .crtc = crtc, - .plane = plane, - .buffer = NULL, - }; - - update->plane_assignments = g_list_prepend (update->plane_assignments, - plane_assignment); - - return plane_assignment; -} - -void -meta_kms_update_mode_set (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - GList *connectors, - MetaKmsMode *mode) -{ - MetaKmsModeSet *mode_set; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_crtc_get_device (crtc) == update->device); - g_assert (!update->power_save); - - mode_set = g_new0 (MetaKmsModeSet, 1); - *mode_set = (MetaKmsModeSet) { - .crtc = crtc, - .connectors = connectors, - .mode = mode, - }; - - update->mode_sets = g_list_prepend (update->mode_sets, mode_set); -} - -static MetaKmsConnectorUpdate * -ensure_connector_update (MetaKmsUpdate *update, - MetaKmsConnector *connector) -{ - GList *l; - MetaKmsConnectorUpdate *connector_update; - - for (l = update->connector_updates; l; l = l->next) - { - connector_update = l->data; - - if (connector_update->connector == connector) - return connector_update; - } - - connector_update = g_new0 (MetaKmsConnectorUpdate, 1); - connector_update->connector = connector; - - update->connector_updates = g_list_prepend (update->connector_updates, - connector_update); - - return connector_update; -} - -void -meta_kms_update_set_underscanning (MetaKmsUpdate *update, - MetaKmsConnector *connector, - uint64_t hborder, - uint64_t vborder) -{ - MetaKmsConnectorUpdate *connector_update; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_connector_get_device (connector) == update->device); - g_assert (!update->power_save); - - connector_update = ensure_connector_update (update, connector); - connector_update->underscanning.has_update = TRUE; - connector_update->underscanning.is_active = TRUE; - connector_update->underscanning.hborder = hborder; - connector_update->underscanning.vborder = vborder; -} - -void -meta_kms_update_unset_underscanning (MetaKmsUpdate *update, - MetaKmsConnector *connector) -{ - MetaKmsConnectorUpdate *connector_update; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_connector_get_device (connector) == update->device); - g_assert (!update->power_save); - - connector_update = ensure_connector_update (update, connector); - connector_update->underscanning.has_update = TRUE; - connector_update->underscanning.is_active = FALSE; -} - -void -meta_kms_update_set_power_save (MetaKmsUpdate *update) -{ - g_assert (!meta_kms_update_is_locked (update)); - g_assert (!update->mode_sets); - g_assert (!update->plane_assignments); - g_assert (!update->connector_updates); - g_assert (!update->crtc_gammas); - - update->power_save = TRUE; -} - -void -meta_kms_crtc_gamma_free (MetaKmsCrtcGamma *gamma) -{ - g_free (gamma->red); - g_free (gamma->green); - g_free (gamma->blue); - g_free (gamma); -} - -MetaKmsCrtcGamma * -meta_kms_crtc_gamma_new (MetaKmsCrtc *crtc, - int size, - const uint16_t *red, - const uint16_t *green, - const uint16_t *blue) -{ - MetaKmsCrtcGamma *gamma; - - gamma = g_new0 (MetaKmsCrtcGamma, 1); - *gamma = (MetaKmsCrtcGamma) { - .crtc = crtc, - .size = size, - .red = g_memdup2 (red, size * sizeof (*red)), - .green = g_memdup2 (green, size * sizeof (*green)), - .blue = g_memdup2 (blue, size * sizeof (*blue)), - }; - - return gamma; -} - -void -meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - int size, - const uint16_t *red, - const uint16_t *green, - const uint16_t *blue) -{ - MetaKmsCrtcGamma *gamma; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_crtc_get_device (crtc) == update->device); - g_assert (!update->power_save); - - gamma = meta_kms_crtc_gamma_new (crtc, size, red, green, blue); - - update->crtc_gammas = g_list_prepend (update->crtc_gammas, gamma); -} - -void -meta_kms_update_add_page_flip_listener (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - const MetaKmsPageFlipListenerVtable *vtable, - MetaKmsPageFlipListenerFlag flags, - gpointer user_data, - GDestroyNotify destroy_notify) -{ - MetaKmsPageFlipListener *listener; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_crtc_get_device (crtc) == update->device); - - listener = g_new0 (MetaKmsPageFlipListener, 1); - *listener = (MetaKmsPageFlipListener) { - .crtc = crtc, - .vtable = vtable, - .flags = flags, - .user_data = user_data, - .destroy_notify = destroy_notify, - }; - - update->page_flip_listeners = g_list_prepend (update->page_flip_listeners, - listener); -} - -void -meta_kms_update_drop_defunct_page_flip_listeners (MetaKmsUpdate *update) -{ - GList *l; - - l = update->page_flip_listeners; - while (l) - { - MetaKmsPageFlipListener *listener = l->data; - GList *l_next = l->next; - - if (listener->flags & META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR) - { - meta_kms_page_flip_listener_free (listener); - update->page_flip_listeners = - g_list_delete_link (update->page_flip_listeners, l); - } - - l = l_next; - } -} - -void -meta_kms_update_set_custom_page_flip (MetaKmsUpdate *update, - MetaKmsCustomPageFlipFunc func, - gpointer user_data) -{ - MetaKmsCustomPageFlip *custom_page_flip; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (!update->power_save); - - custom_page_flip = g_new0 (MetaKmsCustomPageFlip, 1); - custom_page_flip->func = func; - custom_page_flip->user_data = user_data; - - update->custom_page_flip = custom_page_flip; -} - -void -meta_kms_plane_assignment_set_rotation (MetaKmsPlaneAssignment *plane_assignment, - uint64_t rotation) -{ - g_assert (!meta_kms_update_is_locked (plane_assignment->update)); - g_warn_if_fail (rotation); - - plane_assignment->rotation = rotation; -} - -void -meta_kms_plane_assignment_set_cursor_hotspot (MetaKmsPlaneAssignment *plane_assignment, - int x, - int y) -{ - plane_assignment->cursor_hotspot.is_valid = TRUE; - plane_assignment->cursor_hotspot.x = x; - plane_assignment->cursor_hotspot.y = y; -} - -void -meta_kms_update_add_result_listener (MetaKmsUpdate *update, - MetaKmsResultListenerFunc func, - gpointer user_data) -{ - MetaKmsResultListener *listener; - - listener = g_new0 (MetaKmsResultListener, 1); - *listener = (MetaKmsResultListener) { - .func = func, - .user_data = user_data, - }; - - update->result_listeners = g_list_append (update->result_listeners, - listener); -} - -GList * -meta_kms_update_take_result_listeners (MetaKmsUpdate *update) -{ - return g_steal_pointer (&update->result_listeners); -} - -void -meta_kms_result_listener_notify (MetaKmsResultListener *listener, - const MetaKmsFeedback *feedback) -{ - listener->func (feedback, listener->user_data); -} - -void -meta_kms_result_listener_free (MetaKmsResultListener *listener) -{ - g_free (listener); -} - -MetaKmsPlaneAssignment * -meta_kms_update_get_primary_plane_assignment (MetaKmsUpdate *update, - MetaKmsCrtc *crtc) -{ - GList *l; - - for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next) - { - MetaKmsPlaneAssignment *plane_assignment = l->data; - - if (meta_kms_plane_get_plane_type (plane_assignment->plane) != - META_KMS_PLANE_TYPE_PRIMARY) - continue; - - if (plane_assignment->crtc != crtc) - continue; - - return plane_assignment; - } - - return NULL; -} - -GList * -meta_kms_update_get_plane_assignments (MetaKmsUpdate *update) -{ - return update->plane_assignments; -} - -GList * -meta_kms_update_get_mode_sets (MetaKmsUpdate *update) -{ - return update->mode_sets; -} - -GList * -meta_kms_update_get_page_flip_listeners (MetaKmsUpdate *update) -{ - return update->page_flip_listeners; -} - -GList * -meta_kms_update_get_connector_updates (MetaKmsUpdate *update) -{ - return update->connector_updates; -} - -GList * -meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update) -{ - return update->crtc_gammas; -} - -gboolean -meta_kms_update_is_power_save (MetaKmsUpdate *update) -{ - return update->power_save; -} - -void -meta_kms_update_lock (MetaKmsUpdate *update) -{ - update->is_locked = TRUE; -} - -void -meta_kms_update_unlock (MetaKmsUpdate *update) -{ - update->is_locked = FALSE; -} - -gboolean -meta_kms_update_is_locked (MetaKmsUpdate *update) -{ - return update->is_locked; -} - -MetaKmsDevice * -meta_kms_update_get_device (MetaKmsUpdate *update) -{ - return update->device; -} - -MetaKmsCustomPageFlip * -meta_kms_update_take_custom_page_flip_func (MetaKmsUpdate *update) -{ - return g_steal_pointer (&update->custom_page_flip); -} - -void -meta_kms_custom_page_flip_free (MetaKmsCustomPageFlip *custom_page_flip) -{ - g_free (custom_page_flip); -} - -uint64_t -meta_kms_update_get_sequence_number (MetaKmsUpdate *update) -{ - return update->sequence_number; -} - -MetaKmsUpdate * -meta_kms_update_new (MetaKmsDevice *device) -{ - MetaKmsUpdate *update; - static uint64_t sequence_number = 0; - - update = g_new0 (MetaKmsUpdate, 1); - update->device = device; - update->sequence_number = sequence_number++; - - return update; -} - -void -meta_kms_update_free (MetaKmsUpdate *update) -{ - g_list_free_full (update->result_listeners, - (GDestroyNotify) meta_kms_result_listener_free); - g_list_free_full (update->plane_assignments, - (GDestroyNotify) meta_kms_plane_assignment_free); - g_list_free_full (update->mode_sets, - (GDestroyNotify) meta_kms_mode_set_free); - g_list_free_full (update->page_flip_listeners, - (GDestroyNotify) meta_kms_page_flip_listener_free); - g_list_free_full (update->connector_updates, g_free); - g_list_free_full (update->crtc_gammas, (GDestroyNotify) meta_kms_crtc_gamma_free); - g_clear_pointer (&update->custom_page_flip, meta_kms_custom_page_flip_free); - - g_free (update); -} diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h deleted file mode 100644 index 4a6a8bb43..000000000 --- a/src/backends/native/meta-kms-update.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -#ifndef META_KMS_UPDATE_H -#define META_KMS_UPDATE_H - -#include <glib-object.h> -#include <glib.h> -#include <stdint.h> -#include <xf86drmMode.h> - -#include "backends/meta-monitor-transform.h" -#include "backends/native/meta-drm-buffer.h" -#include "backends/native/meta-kms-types.h" -#include "meta/boxes.h" - -typedef enum _MetaKmsFeedbackResult -{ - META_KMS_FEEDBACK_PASSED, - META_KMS_FEEDBACK_FAILED, -} MetaKmsFeedbackResult; - -typedef enum _MetaKmsAssignPlaneFlag -{ - META_KMS_ASSIGN_PLANE_FLAG_NONE = 0, - META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED = 1 << 0, - META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL = 1 << 1, -} MetaKmsAssignPlaneFlag; - -enum _MetaKmsPageFlipListenerFlag -{ - META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE = 0, - META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR = 1 << 0, -}; - -struct _MetaKmsPageFlipListenerVtable -{ - void (* flipped) (MetaKmsCrtc *crtc, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - gpointer user_data); - - void (* ready) (MetaKmsCrtc *crtc, - gpointer user_data); - - void (* mode_set_fallback) (MetaKmsCrtc *crtc, - gpointer user_data); - - void (* discarded) (MetaKmsCrtc *crtc, - gpointer user_data, - const GError *error); -}; - -typedef int (* MetaKmsCustomPageFlipFunc) (gpointer custom_page_flip_data, - gpointer user_data); - -typedef struct _MetaKmsPlaneFeedback -{ - MetaKmsPlane *plane; - MetaKmsCrtc *crtc; - GError *error; -} MetaKmsPlaneFeedback; - -typedef void (* MetaKmsResultListenerFunc) (const MetaKmsFeedback *feedback, - gpointer user_data); - -void meta_kms_feedback_free (MetaKmsFeedback *feedback); - -MetaKmsFeedbackResult meta_kms_feedback_get_result (const MetaKmsFeedback *feedback); - -GList * meta_kms_feedback_get_failed_planes (const MetaKmsFeedback *feedback); - -const GError * meta_kms_feedback_get_error (const MetaKmsFeedback *feedback); - -MetaKmsUpdate * meta_kms_update_new (MetaKmsDevice *device); - -void meta_kms_update_free (MetaKmsUpdate *update); - -void meta_kms_update_set_underscanning (MetaKmsUpdate *update, - MetaKmsConnector *connector, - uint64_t hborder, - uint64_t vborder); - -void meta_kms_update_unset_underscanning (MetaKmsUpdate *update, - MetaKmsConnector *connector); - -void meta_kms_update_set_power_save (MetaKmsUpdate *update); - -void meta_kms_update_mode_set (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - GList *connectors, - MetaKmsMode *mode); - -void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - int size, - const uint16_t *red, - const uint16_t *green, - const uint16_t *blue); - -MetaKmsPlaneAssignment * meta_kms_update_assign_plane (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - MetaKmsPlane *plane, - MetaDrmBuffer *buffer, - MetaFixed16Rectangle src_rect, - MetaRectangle dst_rect, - MetaKmsAssignPlaneFlag flags); - -MetaKmsPlaneAssignment * meta_kms_update_unassign_plane (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - MetaKmsPlane *plane); - -void meta_kms_update_add_page_flip_listener (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - const MetaKmsPageFlipListenerVtable *vtable, - MetaKmsPageFlipListenerFlag flags, - gpointer user_data, - GDestroyNotify destroy_notify); - -void meta_kms_update_set_custom_page_flip (MetaKmsUpdate *update, - MetaKmsCustomPageFlipFunc func, - gpointer user_data); - -void meta_kms_plane_assignment_set_cursor_hotspot (MetaKmsPlaneAssignment *plane_assignment, - int x, - int y); - -void meta_kms_update_add_result_listener (MetaKmsUpdate *update, - MetaKmsResultListenerFunc func, - gpointer user_data); - -static inline MetaFixed16 -meta_fixed_16_from_int (int16_t d) -{ - return d * 65536; -} - -static inline int16_t -meta_fixed_16_to_int (MetaFixed16 fixed) -{ - return fixed / 65536; -} - -static inline double -meta_fixed_16_to_double (MetaFixed16 fixed) -{ - return fixed / 65536.0; -} - -static inline MetaRectangle -meta_fixed_16_rectangle_to_rectangle (MetaFixed16Rectangle fixed_rect) -{ - return (MetaRectangle) { - .x = meta_fixed_16_to_int (fixed_rect.x), - .y = meta_fixed_16_to_int (fixed_rect.y), - .width = meta_fixed_16_to_int (fixed_rect.width), - .height = meta_fixed_16_to_int (fixed_rect.height), - }; -} - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsFeedback, meta_kms_feedback_free) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsUpdate, meta_kms_update_free) - -#endif /* META_KMS_UPDATE_H */ diff --git a/src/backends/native/meta-kms-utils.c b/src/backends/native/meta-kms-utils.c deleted file mode 100644 index 2289cfa91..000000000 --- a/src/backends/native/meta-kms-utils.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2013-2019 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. - * - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-utils.h" - -#include <drm_fourcc.h> -#include <glib.h> - -/* added in libdrm 2.4.95 */ -#ifndef DRM_FORMAT_INVALID -#define DRM_FORMAT_INVALID 0 -#endif - -float -meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *drm_mode) -{ - double numerator; - double denominator; - - if (drm_mode->htotal <= 0 || drm_mode->vtotal <= 0) - return 0.0; - - numerator = drm_mode->clock * 1000.0; - denominator = (double) drm_mode->vtotal * drm_mode->htotal; - if (drm_mode->vscan > 1) - denominator *= drm_mode->vscan; - - return numerator / denominator; -} - -int64_t -meta_calculate_drm_mode_vblank_duration_us (const drmModeModeInfo *drm_mode) -{ - int64_t value; - - if (drm_mode->htotal <= 0 || drm_mode->vtotal <= 0) - return 0; - - /* Convert to int64_t early. */ - value = drm_mode->vtotal - drm_mode->vdisplay; - value *= drm_mode->htotal; - - if (drm_mode->flags & DRM_MODE_FLAG_DBLSCAN) - value *= 2; - - /* Round the duration up as it is used for buffer swap deadline computation. */ - value = (value * 1000 + drm_mode->clock - 1) / drm_mode->clock; - - return value; -} - -/** - * meta_drm_format_to_string: - * @tmp: temporary buffer - * @drm_format: DRM fourcc pixel format - * - * Returns a pointer to a string naming the given pixel format, - * usually a pointer to the temporary buffer but not always. - * Invalid formats may return nonsense names. - * - * When calling this, allocate one MetaDrmFormatBuf on the stack to - * be used as the temporary buffer. - */ -const char * -meta_drm_format_to_string (MetaDrmFormatBuf *tmp, - uint32_t drm_format) -{ - int i; - - if (drm_format == DRM_FORMAT_INVALID) - return "INVALID"; - - G_STATIC_ASSERT (sizeof (tmp->s) == 5); - for (i = 0; i < 4; i++) - { - char c = (drm_format >> (i * 8)) & 0xff; - tmp->s[i] = g_ascii_isgraph (c) ? c : '.'; - } - - tmp->s[i] = 0; - - return tmp->s; -} - diff --git a/src/backends/native/meta-kms-utils.h b/src/backends/native/meta-kms-utils.h deleted file mode 100644 index 2f2bad1f9..000000000 --- a/src/backends/native/meta-kms-utils.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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. - */ - -#ifndef META_KMS_UTILS_H -#define META_KMS_UTILS_H - -#include <stddef.h> -#include <stdint.h> -#include <xf86drmMode.h> - -#include "core/util-private.h" - -typedef struct _MetaDrmFormatBuf -{ - char s[5]; -} MetaDrmFormatBuf; - -META_EXPORT_TEST -float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *drm_mode); - -META_EXPORT_TEST -int64_t meta_calculate_drm_mode_vblank_duration_us (const drmModeModeInfo *drm_mode); - -const char * meta_drm_format_to_string (MetaDrmFormatBuf *tmp, - uint32_t drm_format); - -#endif /* META_KMS_UTILS_H */ diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c deleted file mode 100644 index 70feccc22..000000000 --- a/src/backends/native/meta-kms.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * Copyright (C) 2018 Red Hat - * Copyright 2020 DisplayLink (UK) Ltd. - * - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-private.h" - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-impl.h" -#include "backends/native/meta-kms-update-private.h" -#include "backends/native/meta-udev.h" -#include "cogl/cogl.h" - -/** - * SECTION:kms - * @short description: KMS abstraction - * @title: KMS abstraction - * - * The KMS abstraction consists of various building blocks for helping out with - * interacting with the various drm API's, enabling users to use a - * transactional API, aiming to hide all interaction with the underlying APIs. - * - * The subsystem defines two separate contexts, the "main" context, and the - * "impl" context. The main context is the context of which mutter as a whole - * runs in. It uses the main GLib main loop and main context and always runs in - * the main thread. - * - * The impl context is where all underlying API is being executed. While in the - * current state, it always runs in the main thread, the aim is to be able to - * execute the impl context in a dedicated thread. - * - * The public facing MetaKms API is always assumed to be executed from the main - * context. - * - * The KMS abstraction consists of the following public components: - * - * #MetaKms: - * - * Main entry point; used by the native backend to create devices, post updates - * etc. - * - * #MetaKmsDevice: - * - * A device (usually /dev/dri/cardN, where N being a number). Used to get KMS - * objects, such as connectors, CRTCs, planes, as well as basic meta data such - * as device path etc. - * - * #MetaKmsCrtc: - * - * Represents a CRTC. It manages a representation of the current CRTC state, - * including current mode, coordinates, possible clones. - * - * #MetaKmsConnector: - * - * Represents a connector, e.g. a display port connection. It also manages a - * representation of the current state, including meta data such as physical - * dimension of the connected, available modes, EDID, tile info etc. It also - * contains helper functions for configuration, as well as methods for adding - * configuration to a transaction (See #MetaKmsUpdate). - * - * #MetaKmsPlane: - * - * Represents a hardware plane. A plane is used to define the content of what - * should be presented on a CRTC. Planes can either be primary planes, used as - * a backdrop for CRTCs, overlay planes, and cursor planes. - * - * #MetaKmsMode: - * - * Represents a mode a CRTC and connector can be configured with. - * Represents both modes directly derived from the devices, as well as - * fall back modes when the CRTC supports scaling. - * - * #MetaKmsUpdate: - * - * A KMS transaction object, meant to be processed potentially atomically when - * posted. An update consists of plane assignments, mode sets and KMS object - * property entries. The user adds updates to the object, and then posts it via - * MetaKms. It will then be processed by the MetaKms backend (See - * #MetaKmsImpl), potentially atomically. Each #MetaKmsUpdate deals with - * updating a single device. - * - * - * There are also these private objects, without public facing API: - * - * #MetaKmsImpl: - * - * The KMS impl context object, managing things in the impl context. - * - * #MetaKmsImplDevice: - * - * An object linked to a #MetaKmsDevice, but where it is executed in the impl - * context. It takes care of the updating of the various KMS object (CRTC, - * connector, ..) states. - * - * This is an abstract type, with currently #MetaKmsImplDeviceSimple, - * implementing mode setting and page flipping using legacy DRM API. - * - * #MetaKmsPageFlip: - * - * A object representing a page flip. It's created when a page flip is queued, - * and contains information necessary to provide feedback to the one requesting - * the page flip. - * - */ - -enum -{ - RESOURCES_CHANGED, - - N_SIGNALS -}; - -static int signals[N_SIGNALS]; - -typedef struct _MetaKmsCallbackData -{ - MetaKmsCallback callback; - gpointer user_data; - GDestroyNotify user_data_destroy; -} MetaKmsCallbackData; - -typedef struct _MetaKmsSimpleImplSource -{ - GSource source; - MetaKms *kms; -} MetaKmsSimpleImplSource; - -typedef struct _MetaKmsFdImplSource -{ - GSource source; - - gpointer fd_tag; - MetaKms *kms; - - MetaKmsImplTaskFunc dispatch; - gpointer user_data; -} MetaKmsFdImplSource; - -struct _MetaKms -{ - GObject parent; - - MetaKmsFlags flags; - - MetaBackend *backend; - - gulong hotplug_handler_id; - gulong removed_handler_id; - - MetaKmsImpl *impl; - gboolean in_impl_task; - gboolean waiting_for_impl_task; - - GList *devices; - - GList *pending_updates; - - GList *pending_callbacks; - guint callback_source_id; -}; - -G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT) - -static void -meta_kms_add_pending_update (MetaKms *kms, - MetaKmsUpdate *update) -{ - kms->pending_updates = g_list_prepend (kms->pending_updates, update); -} - -MetaKmsUpdate * -meta_kms_ensure_pending_update (MetaKms *kms, - MetaKmsDevice *device) -{ - MetaKmsUpdate *update; - - update = meta_kms_get_pending_update (kms, device); - if (update) - return update; - - update = meta_kms_update_new (device); - meta_kms_add_pending_update (kms, update); - - return update; -} - -MetaKmsUpdate * -meta_kms_get_pending_update (MetaKms *kms, - MetaKmsDevice *device) -{ - GList *l; - - for (l = kms->pending_updates; l; l = l->next) - { - MetaKmsUpdate *update = l->data; - - if (meta_kms_update_get_device (update) == device) - return update; - } - - return NULL; -} - -static MetaKmsUpdate * -meta_kms_take_pending_update (MetaKms *kms, - MetaKmsDevice *device) -{ - GList *l; - - for (l = kms->pending_updates; l; l = l->next) - { - MetaKmsUpdate *update = l->data; - - if (meta_kms_update_get_device (update) == device) - { - kms->pending_updates = g_list_delete_link (kms->pending_updates, l); - return update; - } - } - - return NULL; -} - -typedef struct -{ - MetaKmsUpdate *update; - MetaKmsUpdateFlag flags; -} PostUpdateData; - -static gpointer -meta_kms_process_update_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - PostUpdateData *data = user_data; - MetaKmsUpdate *update = data->update; - MetaKmsFeedback *feedback; - - feedback = meta_kms_impl_process_update (impl, data->update, data->flags); - meta_kms_device_predict_states_in_impl (meta_kms_update_get_device (update), - update); - - return feedback; -} - -MetaKmsFeedback * -meta_kms_post_pending_update_sync (MetaKms *kms, - MetaKmsDevice *device, - MetaKmsUpdateFlag flags) -{ - MetaKmsUpdate *update; - PostUpdateData data; - MetaKmsFeedback *feedback; - GList *result_listeners; - GList *l; - - COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync, - "KMS (post update)"); - - update = meta_kms_take_pending_update (kms, device); - if (!update) - return NULL; - - meta_kms_update_lock (update); - - data = (PostUpdateData) { - .update = update, - .flags = flags, - }; - feedback = meta_kms_run_impl_task_sync (kms, - meta_kms_process_update_in_impl, - &data, - NULL); - - result_listeners = meta_kms_update_take_result_listeners (update); - - if (feedback->error && - flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR) - { - GList *l; - - meta_kms_update_unlock (update); - - for (l = feedback->failed_planes; l; l = l->next) - { - MetaKmsPlane *plane = l->data; - - meta_kms_update_drop_plane_assignment (update, plane); - } - - meta_kms_update_drop_defunct_page_flip_listeners (update); - - meta_kms_add_pending_update (kms, update); - } - else - { - meta_kms_update_free (update); - } - - for (l = result_listeners; l; l = l->next) - { - MetaKmsResultListener *listener = l->data; - - meta_kms_result_listener_notify (listener, feedback); - meta_kms_result_listener_free (listener); - } - g_list_free (result_listeners); - - return feedback; -} - -static gpointer -meta_kms_discard_pending_page_flips_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - meta_kms_impl_discard_pending_page_flips (impl); - return GINT_TO_POINTER (TRUE); -} - -void -meta_kms_discard_pending_page_flips (MetaKms *kms) -{ - meta_kms_run_impl_task_sync (kms, - meta_kms_discard_pending_page_flips_in_impl, - NULL, - NULL); -} - -static gpointer -meta_kms_notify_modes_set_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - meta_kms_impl_notify_modes_set (impl); - return GINT_TO_POINTER (TRUE); -} - -void -meta_kms_notify_modes_set (MetaKms *kms) -{ - meta_kms_run_impl_task_sync (kms, - meta_kms_notify_modes_set_in_impl, - NULL, - NULL); -} - -static void -meta_kms_callback_data_free (MetaKmsCallbackData *callback_data) -{ - if (callback_data->user_data_destroy) - callback_data->user_data_destroy (callback_data->user_data); - g_free (callback_data); -} - -static int -flush_callbacks (MetaKms *kms) -{ - GList *l; - int callback_count = 0; - - meta_assert_not_in_kms_impl (kms); - - g_clear_handle_id (&kms->callback_source_id, g_source_remove); - - for (l = kms->pending_callbacks; l; l = l->next) - { - MetaKmsCallbackData *callback_data = l->data; - - callback_data->callback (kms, callback_data->user_data); - meta_kms_callback_data_free (callback_data); - callback_count++; - } - - g_list_free (kms->pending_callbacks); - kms->pending_callbacks = NULL; - - return callback_count; -} - -static gboolean -callback_idle (gpointer user_data) -{ - MetaKms *kms = user_data; - - flush_callbacks (kms); - - kms->callback_source_id = 0; - return G_SOURCE_REMOVE; -} - -void -meta_kms_queue_callback (MetaKms *kms, - MetaKmsCallback callback, - gpointer user_data, - GDestroyNotify user_data_destroy) -{ - MetaKmsCallbackData *callback_data; - - callback_data = g_new0 (MetaKmsCallbackData, 1); - *callback_data = (MetaKmsCallbackData) { - .callback = callback, - .user_data = user_data, - .user_data_destroy = user_data_destroy, - }; - kms->pending_callbacks = g_list_append (kms->pending_callbacks, - callback_data); - if (!kms->callback_source_id) - kms->callback_source_id = g_idle_add (callback_idle, kms); -} - -gpointer -meta_kms_run_impl_task_sync (MetaKms *kms, - MetaKmsImplTaskFunc func, - gpointer user_data, - GError **error) -{ - gpointer ret; - - kms->in_impl_task = TRUE; - kms->waiting_for_impl_task = TRUE; - ret = func (kms->impl, user_data, error); - kms->waiting_for_impl_task = FALSE; - kms->in_impl_task = FALSE; - - return ret; -} - -static gboolean -simple_impl_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - MetaKmsSimpleImplSource *simple_impl_source = - (MetaKmsSimpleImplSource *) source; - MetaKms *kms = simple_impl_source->kms; - gboolean ret; - - kms->in_impl_task = TRUE; - ret = callback (user_data); - kms->in_impl_task = FALSE; - - return ret; -} - -static GSourceFuncs simple_impl_source_funcs = { - .dispatch = simple_impl_source_dispatch, -}; - -GSource * -meta_kms_add_source_in_impl (MetaKms *kms, - GSourceFunc func, - gpointer user_data, - GDestroyNotify user_data_destroy) -{ - GSource *source; - MetaKmsSimpleImplSource *simple_impl_source; - - meta_assert_in_kms_impl (kms); - - source = g_source_new (&simple_impl_source_funcs, - sizeof (MetaKmsSimpleImplSource)); - simple_impl_source = (MetaKmsSimpleImplSource *) source; - simple_impl_source->kms = kms; - - g_source_set_callback (source, func, user_data, user_data_destroy); - g_source_set_ready_time (source, 0); - g_source_attach (source, g_main_context_get_thread_default ()); - - return source; -} - -static gboolean -meta_kms_fd_impl_source_check (GSource *source) -{ - MetaKmsFdImplSource *fd_impl_source = (MetaKmsFdImplSource *) source; - - return g_source_query_unix_fd (source, fd_impl_source->fd_tag) & G_IO_IN; -} - -static gboolean -meta_kms_fd_impl_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - MetaKmsFdImplSource *fd_impl_source = (MetaKmsFdImplSource *) source; - MetaKms *kms = fd_impl_source->kms; - gpointer ret; - GError *error = NULL; - - kms->in_impl_task = TRUE; - ret = fd_impl_source->dispatch (kms->impl, - fd_impl_source->user_data, - &error); - kms->in_impl_task = FALSE; - - if (!GPOINTER_TO_INT (ret)) - { - g_warning ("Failed to dispatch fd source: %s", error->message); - g_error_free (error); - } - - return G_SOURCE_CONTINUE; -} - -static GSourceFuncs fd_impl_source_funcs = { - NULL, - meta_kms_fd_impl_source_check, - meta_kms_fd_impl_source_dispatch -}; - -GSource * -meta_kms_register_fd_in_impl (MetaKms *kms, - int fd, - MetaKmsImplTaskFunc dispatch, - gpointer user_data) -{ - GSource *source; - MetaKmsFdImplSource *fd_impl_source; - - meta_assert_in_kms_impl (kms); - - source = g_source_new (&fd_impl_source_funcs, sizeof (MetaKmsFdImplSource)); - fd_impl_source = (MetaKmsFdImplSource *) source; - fd_impl_source->dispatch = dispatch; - fd_impl_source->user_data = user_data; - fd_impl_source->kms = kms; - fd_impl_source->fd_tag = g_source_add_unix_fd (source, fd, - G_IO_IN | G_IO_ERR); - - g_source_attach (source, g_main_context_get_thread_default ()); - - return source; -} - -gboolean -meta_kms_in_impl_task (MetaKms *kms) -{ - return kms->in_impl_task; -} - -gboolean -meta_kms_is_waiting_for_impl_task (MetaKms *kms) -{ - return kms->waiting_for_impl_task; -} - -static void -meta_kms_update_states_in_impl (MetaKms *kms) -{ - COGL_TRACE_BEGIN_SCOPED (MetaKmsUpdateStates, - "KMS (update states)"); - - meta_assert_in_kms_impl (kms); - - g_list_foreach (kms->devices, - (GFunc) meta_kms_device_update_states_in_impl, - NULL); -} - -static gpointer -update_states_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - MetaKms *kms = meta_kms_impl_get_kms (impl); - - meta_kms_update_states_in_impl (kms); - - return GINT_TO_POINTER (TRUE); -} - -static gboolean -meta_kms_update_states_sync (MetaKms *kms, - GError **error) -{ - gpointer ret; - - ret = meta_kms_run_impl_task_sync (kms, update_states_in_impl, NULL, error); - return GPOINTER_TO_INT (ret); -} - -static void -handle_hotplug_event (MetaKms *kms) -{ - g_autoptr (GError) error = NULL; - - if (!meta_kms_update_states_sync (kms, &error)) - g_warning ("Updating KMS state failed: %s", error->message); - - g_signal_emit (kms, signals[RESOURCES_CHANGED], 0); -} - -void -meta_kms_resume (MetaKms *kms) -{ - handle_hotplug_event (kms); -} - -static void -on_udev_hotplug (MetaUdev *udev, - MetaKms *kms) -{ - handle_hotplug_event (kms); -} - -static void -on_udev_device_removed (MetaUdev *udev, - GUdevDevice *device, - MetaKms *kms) -{ - handle_hotplug_event (kms); -} - -MetaBackend * -meta_kms_get_backend (MetaKms *kms) -{ - return kms->backend; -} - -GList * -meta_kms_get_devices (MetaKms *kms) -{ - return kms->devices; -} - -MetaKmsDevice * -meta_kms_create_device (MetaKms *kms, - const char *path, - MetaKmsDeviceFlag flags, - GError **error) -{ - MetaKmsDevice *device; - - if (kms->flags & META_KMS_FLAG_NO_MODE_SETTING) - flags |= META_KMS_DEVICE_FLAG_NO_MODE_SETTING; - - device = meta_kms_device_new (kms, path, flags, error); - if (!device) - return NULL; - - kms->devices = g_list_append (kms->devices, device); - - return device; -} - -MetaKms * -meta_kms_new (MetaBackend *backend, - MetaKmsFlags flags, - GError **error) -{ - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaUdev *udev = meta_backend_native_get_udev (backend_native); - MetaKms *kms; - - kms = g_object_new (META_TYPE_KMS, NULL); - kms->flags = flags; - kms->backend = backend; - kms->impl = meta_kms_impl_new (kms); - if (!kms->impl) - { - g_object_unref (kms); - return NULL; - } - - if (!(flags & META_KMS_FLAG_NO_MODE_SETTING)) - { - kms->hotplug_handler_id = - g_signal_connect (udev, "hotplug", G_CALLBACK (on_udev_hotplug), kms); - } - - kms->removed_handler_id = - g_signal_connect (udev, "device-removed", - G_CALLBACK (on_udev_device_removed), kms); - - return kms; -} - -static gpointer -prepare_shutdown_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - meta_kms_impl_prepare_shutdown (impl); - return GINT_TO_POINTER (TRUE); -} - -void -meta_kms_prepare_shutdown (MetaKms *kms) -{ - meta_kms_run_impl_task_sync (kms, prepare_shutdown_in_impl, NULL, NULL); - flush_callbacks (kms); -} - -static void -meta_kms_finalize (GObject *object) -{ - MetaKms *kms = META_KMS (object); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (kms->backend); - MetaUdev *udev = meta_backend_native_get_udev (backend_native); - GList *l; - - for (l = kms->pending_callbacks; l; l = l->next) - meta_kms_callback_data_free (l->data); - g_list_free (kms->pending_callbacks); - - g_clear_handle_id (&kms->callback_source_id, g_source_remove); - - g_list_free_full (kms->devices, g_object_unref); - - g_clear_signal_handler (&kms->hotplug_handler_id, udev); - g_clear_signal_handler (&kms->removed_handler_id, udev); - - G_OBJECT_CLASS (meta_kms_parent_class)->finalize (object); -} - -static void -meta_kms_init (MetaKms *kms) -{ -} - -static void -meta_kms_class_init (MetaKmsClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_kms_finalize; - - signals[RESOURCES_CHANGED] = - g_signal_new ("resources-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h deleted file mode 100644 index 9eae80e3f..000000000 --- a/src/backends/native/meta-kms.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -#ifndef META_KMS_H -#define META_KMS_H - -#include <glib-object.h> - -#include "backends/meta-backend-private.h" -#include "backends/native/meta-kms-types.h" - -typedef enum _MetaKmsFlags -{ - META_KMS_FLAG_NONE = 0, - META_KMS_FLAG_NO_MODE_SETTING = 1 << 0, -} MetaKmsFlags; - -typedef enum _MetaKmsUpdateFlag -{ - META_KMS_UPDATE_FLAG_NONE = 0, - META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR = 1 << 0, -} MetaKmsUpdateFlag; - -#define META_TYPE_KMS (meta_kms_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKms, meta_kms, META, KMS, GObject) - -MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms *kms, - MetaKmsDevice *device); - -MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms, - MetaKmsDevice *device); - -MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms, - MetaKmsDevice *device, - MetaKmsUpdateFlag flags); - -void meta_kms_discard_pending_page_flips (MetaKms *kms); - -void meta_kms_notify_modes_set (MetaKms *kms); - -MetaBackend * meta_kms_get_backend (MetaKms *kms); - -GList * meta_kms_get_devices (MetaKms *kms); - -void meta_kms_resume (MetaKms *kms); - -MetaKmsDevice * meta_kms_create_device (MetaKms *kms, - const char *path, - MetaKmsDeviceFlag flags, - GError **error); - -void meta_kms_prepare_shutdown (MetaKms *kms); - -MetaKms * meta_kms_new (MetaBackend *backend, - MetaKmsFlags flags, - GError **error); - -#endif /* META_KMS_H */ diff --git a/src/backends/native/meta-launcher.c b/src/backends/native/meta-launcher.c deleted file mode 100644 index 4a63d2feb..000000000 --- a/src/backends/native/meta-launcher.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (C) 2013 Red Hat, Inc. - * - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-launcher.h" - -#include <gio/gunixfdlist.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/sysmacros.h> -#include <malloc.h> -#include <fcntl.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <systemd/sd-login.h> -#include <gudev/gudev.h> - -#include "backends/meta-backend-private.h" -#include "backends/native/dbus-utils.h" -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-clutter-backend-native.h" -#include "backends/native/meta-cursor-renderer-native.h" -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-renderer-native.h" -#include "clutter/clutter.h" - -#include "meta-dbus-login1.h" - -struct _MetaLauncher -{ - MetaDbusLogin1Session *session_proxy; - MetaDbusLogin1Seat *seat_proxy; - char *seat_id; - - gboolean session_active; -}; - -const char * -meta_launcher_get_seat_id (MetaLauncher *launcher) -{ - return launcher->seat_id; -} - -static gboolean -find_systemd_session (gchar **session_id, - GError **error) -{ - const gchar * const graphical_session_types[] = { "wayland", "x11", "mir", NULL }; - const gchar * const active_states[] = { "active", "online", NULL }; - g_autofree gchar *class = NULL; - g_autofree gchar *local_session_id = NULL; - g_autofree gchar *type = NULL; - g_autofree gchar *state = NULL; - g_auto (GStrv) sessions = NULL; - int n_sessions; - int saved_errno; - - g_assert (session_id != NULL); - g_assert (error == NULL || *error == NULL); - - /* if we are in a logind session, we can trust that value, so use it. This - * happens for example when you run mutter directly from a VT but when - * systemd starts us we will not be in a logind session. */ - saved_errno = sd_pid_get_session (0, &local_session_id); - if (saved_errno < 0) - { - if (saved_errno != -ENODATA) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Failed to get session by pid for user %d (%s)", - getuid (), - g_strerror (-saved_errno)); - return FALSE; - } - } - else - { - *session_id = g_steal_pointer (&local_session_id); - return TRUE; - } - - saved_errno = sd_uid_get_display (getuid (), &local_session_id); - if (saved_errno < 0) - { - /* no session, maybe there's a greeter session */ - if (saved_errno == -ENODATA) - { - n_sessions = sd_uid_get_sessions (getuid (), 1, &sessions); - if (n_sessions < 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Failed to get all sessions for user %d (%m)", - getuid ()); - return FALSE; - } - - if (n_sessions == 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "User %d has no sessions", - getuid ()); - return FALSE; - } - - for (int i = 0; i < n_sessions; ++i) - { - saved_errno = sd_session_get_class (sessions[i], &class); - if (saved_errno < 0) - { - g_warning ("Couldn't get class for session '%d': %s", - i, - g_strerror (-saved_errno)); - continue; - } - - if (g_strcmp0 (class, "greeter") == 0) - { - local_session_id = g_strdup (sessions[i]); - break; - } - } - - if (!local_session_id) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Couldn't find a session or a greeter session for user %d", - getuid ()); - return FALSE; - } - } - else - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Couldn't get display for user %d: %s", - getuid (), - g_strerror (-saved_errno)); - return FALSE; - } - } - - /* sd_uid_get_display will return any session if there is no graphical - * one, so let's check it really is graphical. */ - saved_errno = sd_session_get_type (local_session_id, &type); - if (saved_errno < 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Couldn't get type for session '%s': %s", - local_session_id, - g_strerror (-saved_errno)); - return FALSE; - } - - if (!g_strv_contains (graphical_session_types, type)) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Session '%s' is not a graphical session (type: '%s')", - local_session_id, - type); - return FALSE; - } - - /* and display sessions can be 'closing' if they are logged out but - * some processes are lingering; we shouldn't consider these */ - saved_errno = sd_session_get_state (local_session_id, &state); - if (saved_errno < 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Couldn't get state for session '%s': %s", - local_session_id, - g_strerror (-saved_errno)); - return FALSE; - } - - if (!g_strv_contains (active_states, state)) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Session '%s' is not active", - local_session_id); - return FALSE; - } - - *session_id = g_steal_pointer (&local_session_id); - - return TRUE; -} - -static MetaDbusLogin1Session * -get_session_proxy (GCancellable *cancellable, - GError **error) -{ - g_autofree char *proxy_path = NULL; - g_autofree char *session_id = NULL; - g_autoptr (GError) local_error = NULL; - GDBusProxyFlags flags; - MetaDbusLogin1Session *session_proxy; - - if (!find_systemd_session (&session_id, &local_error)) - { - g_propagate_prefixed_error (error, - g_steal_pointer (&local_error), - "Could not get session ID: "); - return NULL; - } - - proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/session", session_id); - - flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START; - session_proxy = - meta_dbus_login1_session_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - flags, - "org.freedesktop.login1", - proxy_path, - cancellable, error); - if (!session_proxy) - g_prefix_error(error, "Could not get session proxy: "); - - return session_proxy; -} - -static MetaDbusLogin1Seat * -get_seat_proxy (gchar *seat_id, - GCancellable *cancellable, - GError **error) -{ - g_autofree char *seat_proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/seat", seat_id); - GDBusProxyFlags flags; - MetaDbusLogin1Seat *seat; - - flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START; - seat = - meta_dbus_login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - flags, - "org.freedesktop.login1", - seat_proxy_path, - cancellable, error); - if (!seat) - g_prefix_error(error, "Could not get seat proxy: "); - - return seat; -} - -static void -sync_active (MetaLauncher *self) -{ - MetaBackend *backend = meta_get_backend (); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaDbusLogin1Session *session_proxy = self->session_proxy; - gboolean active; - - active = meta_dbus_login1_session_get_active (session_proxy); - if (active == self->session_active) - return; - - self->session_active = active; - - if (active) - meta_backend_native_resume (backend_native); - else - meta_backend_native_pause (backend_native); -} - -static void -on_active_changed (MetaDbusLogin1Session *session, - GParamSpec *pspec, - gpointer user_data) -{ - MetaLauncher *self = user_data; - sync_active (self); -} - -static gchar * -get_seat_id (GError **error) -{ - g_autoptr (GError) local_error = NULL; - g_autofree char *session_id = NULL; - char *seat_id = NULL; - int r; - - if (!find_systemd_session (&session_id, &local_error)) - { - g_propagate_prefixed_error (error, - g_steal_pointer (&local_error), - "Could not get session ID: "); - return NULL; - } - - r = sd_session_get_seat (session_id, &seat_id); - if (r < 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Could not get seat for session: %s", g_strerror (-r)); - return NULL; - } - - return seat_id; -} - -MetaDbusLogin1Session * -meta_launcher_get_session_proxy (MetaLauncher *launcher) -{ - return launcher->session_proxy; -} - -MetaLauncher * -meta_launcher_new (GError **error) -{ - MetaLauncher *self = NULL; - g_autoptr (MetaDbusLogin1Session) session_proxy = NULL; - g_autoptr (MetaDbusLogin1Seat) seat_proxy = NULL; - g_autofree char *seat_id = NULL; - gboolean have_control = FALSE; - - session_proxy = get_session_proxy (NULL, error); - if (!session_proxy) - goto fail; - - if (!meta_dbus_login1_session_call_take_control_sync (session_proxy, - FALSE, - NULL, - error)) - { - g_prefix_error (error, "Could not take control: "); - goto fail; - } - - have_control = TRUE; - - seat_id = get_seat_id (error); - if (!seat_id) - goto fail; - - seat_proxy = get_seat_proxy (seat_id, NULL, error); - if (!seat_proxy) - goto fail; - - self = g_new0 (MetaLauncher, 1); - self->session_proxy = g_object_ref (session_proxy); - self->seat_proxy = g_object_ref (seat_proxy); - self->seat_id = g_steal_pointer (&seat_id); - self->session_active = TRUE; - - g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self); - - return self; - - fail: - if (have_control) - { - meta_dbus_login1_session_call_release_control_sync (session_proxy, - NULL, NULL); - } - return NULL; -} - -void -meta_launcher_free (MetaLauncher *self) -{ - g_free (self->seat_id); - g_object_unref (self->seat_proxy); - g_object_unref (self->session_proxy); - g_free (self); -} - -gboolean -meta_launcher_activate_vt (MetaLauncher *launcher, - signed char vt, - GError **error) -{ - return meta_dbus_login1_seat_call_switch_to_sync (launcher->seat_proxy, vt, - NULL, error); -} diff --git a/src/backends/native/meta-launcher.h b/src/backends/native/meta-launcher.h deleted file mode 100644 index 267b68337..000000000 --- a/src/backends/native/meta-launcher.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2013 Red Hat, Inc. - * - * 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. - */ - -#ifndef META_LAUNCHER_H -#define META_LAUNCHER_H - -#include <glib-object.h> - -typedef struct _MetaLauncher MetaLauncher; -typedef struct _MetaDbusLogin1Session MetaDbusLogin1Session; - -MetaLauncher *meta_launcher_new (GError **error); -void meta_launcher_free (MetaLauncher *self); - -gboolean meta_launcher_activate_vt (MetaLauncher *self, - signed char vt, - GError **error); - -const char * meta_launcher_get_seat_id (MetaLauncher *launcher); - -MetaDbusLogin1Session * meta_launcher_get_session_proxy (MetaLauncher *launcher); - - -#endif /* META_LAUNCHER_H */ diff --git a/src/backends/native/meta-monitor-manager-native.c b/src/backends/native/meta-monitor-manager-native.c deleted file mode 100644 index fd5e7784f..000000000 --- a/src/backends/native/meta-monitor-manager-native.c +++ /dev/null @@ -1,825 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013 Red Hat Inc. - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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. - * - * Author: Giovanni Campagna <gcampagn@redhat.com> - */ - -/** - * SECTION:meta-monitor-manager-native - * @title: MetaMonitorManagerNative - * @short_description: A subclass of #MetaMonitorManager using Linux DRM - * - * #MetaMonitorManagerNative is a subclass of #MetaMonitorManager which - * implements its functionality "natively": it uses the appropriate - * functions of the Linux DRM kernel module and using a udev client. - * - * See also #MetaMonitorManagerXrandr for an implementation using XRandR. - */ - -#include "config.h" - -#include "backends/native/meta-monitor-manager-native.h" - -#include <drm.h> -#include <errno.h> -#include <gudev/gudev.h> -#include <stdlib.h> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <unistd.h> - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-output.h" -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-gpu-kms.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-launcher.h" -#include "backends/native/meta-output-kms.h" -#include "backends/native/meta-renderer-native.h" -#include "backends/native/meta-virtual-monitor-native.h" -#include "clutter/clutter.h" -#include "meta/main.h" -#include "meta/meta-x11-errors.h" - -enum -{ - PROP_0, - - PROP_NEED_OUTPUTS, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -struct _MetaMonitorManagerNative -{ - MetaMonitorManager parent_instance; - - gulong kms_resources_changed_handler_id; - - GHashTable *crtc_gamma_cache; - - gboolean needs_outputs; -}; - -struct _MetaMonitorManagerNativeClass -{ - MetaMonitorManagerClass parent_class; -}; - -#define VIRTUAL_OUTPUT_ID_BIT (((uint64_t) 1) << 63) - -static void -initable_iface_init (GInitableIface *initable_iface); - -G_DEFINE_TYPE_WITH_CODE (MetaMonitorManagerNative, meta_monitor_manager_native, - META_TYPE_MONITOR_MANAGER, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static GBytes * -meta_monitor_manager_native_read_edid (MetaMonitorManager *manager, - MetaOutput *output) -{ - return meta_output_native_read_edid (META_OUTPUT_NATIVE (output)); -} - -static void -meta_monitor_manager_native_read_current_state (MetaMonitorManager *manager) -{ - MetaMonitorManagerClass *parent_class = - META_MONITOR_MANAGER_CLASS (meta_monitor_manager_native_parent_class); - MetaPowerSave power_save_mode; - - power_save_mode = meta_monitor_manager_get_power_save_mode (manager); - if (power_save_mode != META_POWER_SAVE_ON) - meta_monitor_manager_power_save_mode_changed (manager, - META_POWER_SAVE_ON); - - parent_class->read_current_state (manager); -} - -uint64_t -meta_power_save_to_dpms_state (MetaPowerSave power_save) -{ - switch (power_save) - { - case META_POWER_SAVE_ON: - return DRM_MODE_DPMS_ON; - case META_POWER_SAVE_STANDBY: - return DRM_MODE_DPMS_STANDBY; - case META_POWER_SAVE_SUSPEND: - return DRM_MODE_DPMS_SUSPEND; - case META_POWER_SAVE_OFF: - return DRM_MODE_DPMS_OFF; - case META_POWER_SAVE_UNSUPPORTED: - return DRM_MODE_DPMS_ON; - } - - g_warn_if_reached (); - return DRM_MODE_DPMS_ON; -} - -static void -meta_monitor_manager_native_set_power_save_mode (MetaMonitorManager *manager, - MetaPowerSave mode) -{ - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - GList *l; - - for (l = meta_backend_get_gpus (backend); l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - - switch (mode) - { - case META_POWER_SAVE_ON: - case META_POWER_SAVE_UNSUPPORTED: - { - g_list_foreach (meta_gpu_get_crtcs (META_GPU (gpu_kms)), - (GFunc) meta_crtc_kms_invalidate_gamma, - NULL); - break; - } - case META_POWER_SAVE_STANDBY: - case META_POWER_SAVE_SUSPEND: - case META_POWER_SAVE_OFF: - { - MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - MetaKmsUpdate *kms_update; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_kms_update_set_power_save (kms_update); - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, - kms_device, - flags); - if (meta_kms_feedback_get_result (kms_feedback) != - META_KMS_FEEDBACK_PASSED) - { - g_warning ("Failed to enter power saving mode: %s", - meta_kms_feedback_get_error (kms_feedback)->message); - } - break; - } - } - } -} - -static void -meta_monitor_manager_native_ensure_initial_config (MetaMonitorManager *manager) -{ - MetaMonitorsConfig *config; - - config = meta_monitor_manager_ensure_configured (manager); - - meta_monitor_manager_update_logical_state (manager, config); -} - -static void -apply_crtc_assignments (MetaMonitorManager *manager, - MetaCrtcAssignment **crtcs, - unsigned int n_crtcs, - MetaOutputAssignment **outputs, - unsigned int n_outputs) -{ - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - g_autoptr (GList) to_configure_outputs = NULL; - g_autoptr (GList) to_configure_crtcs = NULL; - unsigned i; - GList *gpus; - GList *l; - - gpus = meta_backend_get_gpus (backend); - for (l = gpus; l; l = l->next) - { - MetaGpu *gpu = l->data; - GList *crtcs; - GList *outputs; - - outputs = g_list_copy (meta_gpu_get_outputs (gpu)); - to_configure_outputs = g_list_concat (to_configure_outputs, outputs); - - crtcs = g_list_copy (meta_gpu_get_crtcs (gpu)); - to_configure_crtcs = g_list_concat (to_configure_crtcs, crtcs); - } - - for (l = meta_monitor_manager_get_virtual_monitors (manager); l; l = l->next) - { - MetaVirtualMonitor *virtual_monitor = l->data; - MetaOutput *output = meta_virtual_monitor_get_output (virtual_monitor); - MetaCrtc *crtc = meta_virtual_monitor_get_crtc (virtual_monitor); - - to_configure_outputs = g_list_append (to_configure_outputs, output); - to_configure_crtcs = g_list_append (to_configure_crtcs, crtc); - } - - for (i = 0; i < n_crtcs; i++) - { - MetaCrtcAssignment *crtc_assignment = crtcs[i]; - MetaCrtc *crtc = crtc_assignment->crtc; - - to_configure_crtcs = g_list_remove (to_configure_crtcs, crtc); - - if (crtc_assignment->mode == NULL) - { - meta_crtc_unset_config (crtc); - } - else - { - unsigned int j; - - meta_crtc_set_config (crtc, - &crtc_assignment->layout, - crtc_assignment->mode, - crtc_assignment->transform); - - for (j = 0; j < crtc_assignment->outputs->len; j++) - { - MetaOutput *output = g_ptr_array_index (crtc_assignment->outputs, - j); - MetaOutputAssignment *output_assignment; - - to_configure_outputs = g_list_remove (to_configure_outputs, - output); - - output_assignment = meta_find_output_assignment (outputs, - n_outputs, - output); - meta_output_assign_crtc (output, crtc, output_assignment); - } - } - } - - g_list_foreach (to_configure_crtcs, - (GFunc) meta_crtc_unset_config, - NULL); - g_list_foreach (to_configure_outputs, - (GFunc) meta_output_unassign_crtc, - NULL); -} - -static void -update_screen_size (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - GList *l; - int screen_width = 0; - int screen_height = 0; - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - int right_edge; - int bottom_edge; - - right_edge = (logical_monitor_config->layout.width + - logical_monitor_config->layout.x); - if (right_edge > screen_width) - screen_width = right_edge; - - bottom_edge = (logical_monitor_config->layout.height + - logical_monitor_config->layout.y); - if (bottom_edge > screen_height) - screen_height = bottom_edge; - } - - manager->screen_width = screen_width; - manager->screen_height = screen_height; -} - -static gboolean -meta_monitor_manager_native_apply_monitors_config (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - MetaMonitorsConfigMethod method, - GError **error) -{ - GPtrArray *crtc_assignments; - GPtrArray *output_assignments; - - if (!config) - { - if (!manager->in_init) - { - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - meta_renderer_native_reset_modes (META_RENDERER_NATIVE (renderer)); - } - - manager->screen_width = META_MONITOR_MANAGER_MIN_SCREEN_WIDTH; - manager->screen_height = META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT; - meta_monitor_manager_rebuild (manager, NULL); - return TRUE; - } - - if (!meta_monitor_config_manager_assign (manager, config, - &crtc_assignments, - &output_assignments, - error)) - return FALSE; - - if (method == META_MONITORS_CONFIG_METHOD_VERIFY) - { - g_ptr_array_free (crtc_assignments, TRUE); - g_ptr_array_free (output_assignments, TRUE); - return TRUE; - } - - apply_crtc_assignments (manager, - (MetaCrtcAssignment **) crtc_assignments->pdata, - crtc_assignments->len, - (MetaOutputAssignment **) output_assignments->pdata, - output_assignments->len); - - g_ptr_array_free (crtc_assignments, TRUE); - g_ptr_array_free (output_assignments, TRUE); - - update_screen_size (manager, config); - meta_monitor_manager_rebuild (manager, config); - - return TRUE; -} - -static void -meta_monitor_manager_native_get_crtc_gamma (MetaMonitorManager *manager, - MetaCrtc *crtc, - gsize *size, - unsigned short **red, - unsigned short **green, - unsigned short **blue) -{ - MetaKmsCrtc *kms_crtc; - const MetaKmsCrtcState *crtc_state; - - g_return_if_fail (META_IS_CRTC_KMS (crtc)); - - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); - crtc_state = meta_kms_crtc_get_current_state (kms_crtc); - - *size = crtc_state->gamma.size; - *red = g_memdup2 (crtc_state->gamma.red, *size * sizeof **red); - *green = g_memdup2 (crtc_state->gamma.green, *size * sizeof **green); - *blue = g_memdup2 (crtc_state->gamma.blue, *size * sizeof **blue); -} - -static char * -generate_gamma_ramp_string (size_t size, - unsigned short *red, - unsigned short *green, - unsigned short *blue) -{ - GString *string; - int color; - - string = g_string_new ("["); - for (color = 0; color < 3; color++) - { - unsigned short **color_ptr = NULL; - char color_char; - size_t i; - - switch (color) - { - case 0: - color_ptr = &red; - color_char = 'r'; - break; - case 1: - color_ptr = &green; - color_char = 'g'; - break; - case 2: - color_ptr = &blue; - color_char = 'b'; - break; - } - - g_assert (color_ptr); - g_string_append_printf (string, " %c: ", color_char); - for (i = 0; i < MIN (4, size); i++) - { - int j; - - if (size > 4) - { - if (i == 2) - g_string_append (string, ",..."); - - if (i >= 2) - j = i + (size - 4); - else - j = i; - } - else - { - j = i; - } - g_string_append_printf (string, "%s%hu", - j == 0 ? "" : ",", - (*color_ptr)[i]); - } - } - - g_string_append (string, " ]"); - - return g_string_free (string, FALSE); -} - -MetaKmsCrtcGamma * -meta_monitor_manager_native_get_cached_crtc_gamma (MetaMonitorManagerNative *manager_native, - MetaCrtcKms *crtc_kms) -{ - uint64_t crtc_id; - - crtc_id = meta_crtc_get_id (META_CRTC (crtc_kms)); - return g_hash_table_lookup (manager_native->crtc_gamma_cache, - GUINT_TO_POINTER (crtc_id)); -} - -static void -meta_monitor_manager_native_set_crtc_gamma (MetaMonitorManager *manager, - MetaCrtc *crtc, - gsize size, - unsigned short *red, - unsigned short *green, - unsigned short *blue) -{ - MetaMonitorManagerNative *manager_native = - META_MONITOR_MANAGER_NATIVE (manager); - MetaCrtcKms *crtc_kms; - MetaKmsCrtc *kms_crtc; - g_autofree char *gamma_ramp_string = NULL; - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - - g_return_if_fail (META_IS_CRTC_KMS (crtc)); - - crtc_kms = META_CRTC_KMS (crtc); - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); - - g_hash_table_replace (manager_native->crtc_gamma_cache, - GUINT_TO_POINTER (meta_crtc_get_id (crtc)), - meta_kms_crtc_gamma_new (kms_crtc, size, - red, green, blue)); - - gamma_ramp_string = generate_gamma_ramp_string (size, red, green, blue); - g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") gamma to %s", - meta_crtc_get_id (crtc), gamma_ramp_string); - - meta_crtc_kms_invalidate_gamma (crtc_kms); - clutter_stage_schedule_update (stage); -} - -static void -handle_hotplug_event (MetaMonitorManager *manager) -{ - meta_monitor_manager_reload (manager); -} - -static void -on_kms_resources_changed (MetaKms *kms, - MetaMonitorManager *manager) -{ - handle_hotplug_event (manager); -} - -static void -meta_monitor_manager_native_connect_hotplug_handler (MetaMonitorManagerNative *manager_native) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_native); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - - manager_native->kms_resources_changed_handler_id = - g_signal_connect (kms, "resources-changed", - G_CALLBACK (on_kms_resources_changed), manager); -} - -static void -meta_monitor_manager_native_disconnect_hotplug_handler (MetaMonitorManagerNative *manager_native) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_native); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - - g_clear_signal_handler (&manager_native->kms_resources_changed_handler_id, kms); -} - -void -meta_monitor_manager_native_pause (MetaMonitorManagerNative *manager_native) -{ - meta_monitor_manager_native_disconnect_hotplug_handler (manager_native); -} - -void -meta_monitor_manager_native_resume (MetaMonitorManagerNative *manager_native) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_native); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - GList *l; - - meta_monitor_manager_native_connect_hotplug_handler (manager_native); - - for (l = meta_backend_get_gpus (backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - - g_list_foreach (meta_gpu_get_crtcs (gpu), - (GFunc) meta_crtc_kms_invalidate_gamma, - NULL); - } -} - -static gboolean -meta_monitor_manager_native_is_transform_handled (MetaMonitorManager *manager, - MetaCrtc *crtc, - MetaMonitorTransform transform) -{ - return meta_crtc_native_is_transform_handled (META_CRTC_NATIVE (crtc), - transform); -} - -static float -meta_monitor_manager_native_calculate_monitor_mode_scale (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode) -{ - return meta_monitor_calculate_mode_scale (monitor, monitor_mode); -} - -static float * -meta_monitor_manager_native_calculate_supported_scales (MetaMonitorManager *manager, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - int *n_supported_scales) -{ - MetaMonitorScalesConstraint constraints = - META_MONITOR_SCALES_CONSTRAINT_NONE; - - switch (layout_mode) - { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: - break; - case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: - constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC; - break; - } - - return meta_monitor_calculate_supported_scales (monitor, monitor_mode, - constraints, - n_supported_scales); -} - -static MetaMonitorManagerCapability -meta_monitor_manager_native_get_capabilities (MetaMonitorManager *manager) -{ - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaSettings *settings = meta_backend_get_settings (backend); - MetaMonitorManagerCapability capabilities = - META_MONITOR_MANAGER_CAPABILITY_NONE; - - if (meta_settings_is_experimental_feature_enabled ( - settings, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER)) - capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE; - - return capabilities; -} - -static gboolean -meta_monitor_manager_native_get_max_screen_size (MetaMonitorManager *manager, - int *max_width, - int *max_height) -{ - return FALSE; -} - -static MetaLogicalMonitorLayoutMode -meta_monitor_manager_native_get_default_layout_mode (MetaMonitorManager *manager) -{ - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaSettings *settings = meta_backend_get_settings (backend); - - if (meta_settings_is_experimental_feature_enabled ( - settings, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER)) - return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL; - else - return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; -} - -static MetaVirtualMonitorNative * -find_virtual_monitor (MetaMonitorManagerNative *manager_native, - uint64_t id) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_native); - GList *l; - - for (l = meta_monitor_manager_get_virtual_monitors (manager); l; l = l->next) - { - MetaVirtualMonitorNative *virtual_monitor_native = l->data; - - if (meta_virtual_monitor_native_get_id (virtual_monitor_native) == id) - return virtual_monitor_native; - } - - return NULL; -} - -static uint64_t -allocate_virtual_monitor_id (MetaMonitorManagerNative *manager_native) -{ - uint64_t id; - - id = 0; - - while (TRUE) - { - if (!find_virtual_monitor (manager_native, id)) - return id; - - id++; - } -} - -static MetaVirtualMonitor * -meta_monitor_manager_native_create_virtual_monitor (MetaMonitorManager *manager, - const MetaVirtualMonitorInfo *info, - GError **error) -{ - MetaMonitorManagerNative *manager_native = - META_MONITOR_MANAGER_NATIVE (manager); - MetaVirtualMonitorNative *virtual_monitor_native; - uint64_t id; - - id = allocate_virtual_monitor_id (manager_native); - virtual_monitor_native = meta_virtual_monitor_native_new (id, info); - return META_VIRTUAL_MONITOR (virtual_monitor_native); -} - -static void -meta_monitor_manager_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaMonitorManagerNative *manager_native = - META_MONITOR_MANAGER_NATIVE (object); - - switch (prop_id) - { - case PROP_NEED_OUTPUTS: - manager_native->needs_outputs = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_monitor_manager_native_dispose (GObject *object) -{ - MetaMonitorManagerNative *manager_native = - META_MONITOR_MANAGER_NATIVE (object); - - g_clear_pointer (&manager_native->crtc_gamma_cache, - g_hash_table_unref); - - G_OBJECT_CLASS (meta_monitor_manager_native_parent_class)->dispose (object); -} - -static gboolean -meta_monitor_manager_native_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaMonitorManagerNative *manager_native = - META_MONITOR_MANAGER_NATIVE (initable); - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_native); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - gboolean can_have_outputs; - GList *l; - - meta_monitor_manager_native_connect_hotplug_handler (manager_native); - - can_have_outputs = FALSE; - for (l = meta_backend_get_gpus (backend); l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - - if (meta_gpu_kms_can_have_outputs (gpu_kms)) - { - can_have_outputs = TRUE; - break; - } - } - - if (manager_native->needs_outputs && !can_have_outputs) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "No GPUs with outputs found"); - return FALSE; - } - - manager_native->crtc_gamma_cache = - g_hash_table_new_full (NULL, NULL, - NULL, - (GDestroyNotify) meta_kms_crtc_gamma_free); - - return TRUE; -} - -static void -initable_iface_init (GInitableIface *initable_iface) -{ - initable_iface->init = meta_monitor_manager_native_initable_init; -} - -static void -meta_monitor_manager_native_init (MetaMonitorManagerNative *manager_native) -{ - manager_native->needs_outputs = TRUE; -} - -static void -meta_monitor_manager_native_class_init (MetaMonitorManagerNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); - - object_class->set_property = meta_monitor_manager_native_set_property; - object_class->dispose = meta_monitor_manager_native_dispose; - - manager_class->read_edid = - meta_monitor_manager_native_read_edid; - manager_class->read_current_state = - meta_monitor_manager_native_read_current_state; - manager_class->ensure_initial_config = - meta_monitor_manager_native_ensure_initial_config; - manager_class->apply_monitors_config = - meta_monitor_manager_native_apply_monitors_config; - manager_class->set_power_save_mode = - meta_monitor_manager_native_set_power_save_mode; - manager_class->get_crtc_gamma = - meta_monitor_manager_native_get_crtc_gamma; - manager_class->set_crtc_gamma = - meta_monitor_manager_native_set_crtc_gamma; - manager_class->is_transform_handled = - meta_monitor_manager_native_is_transform_handled; - manager_class->calculate_monitor_mode_scale = - meta_monitor_manager_native_calculate_monitor_mode_scale; - manager_class->calculate_supported_scales = - meta_monitor_manager_native_calculate_supported_scales; - manager_class->get_capabilities = - meta_monitor_manager_native_get_capabilities; - manager_class->get_max_screen_size = - meta_monitor_manager_native_get_max_screen_size; - manager_class->get_default_layout_mode = - meta_monitor_manager_native_get_default_layout_mode; - manager_class->create_virtual_monitor = - meta_monitor_manager_native_create_virtual_monitor; - - obj_props[PROP_NEED_OUTPUTS] = - g_param_spec_boolean ("needs-outputs", - "needs-outputs", - "Whether any outputs are needed for operation", - TRUE, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/native/meta-monitor-manager-native.h b/src/backends/native/meta-monitor-manager-native.h deleted file mode 100644 index 60f899734..000000000 --- a/src/backends/native/meta-monitor-manager-native.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013 Red Hat Inc. - * - * 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, see <http://www.gnu.org/licenses/>. - */ - -#ifndef META_MONITOR_MANAGER_NATIVE_H -#define META_MONITOR_MANAGER_NATIVE_H - -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include "backends/meta-monitor-manager-private.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-kms-crtc.h" - -typedef struct _MetaGpuKms MetaGpuKms; - -#define META_TYPE_MONITOR_MANAGER_NATIVE (meta_monitor_manager_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaMonitorManagerNative, meta_monitor_manager_native, - META, MONITOR_MANAGER_NATIVE, - MetaMonitorManager) - -void meta_monitor_manager_native_pause (MetaMonitorManagerNative *manager_native); - -void meta_monitor_manager_native_resume (MetaMonitorManagerNative *manager_native); - -uint64_t meta_power_save_to_dpms_state (MetaPowerSave power_save); - -MetaKmsCrtcGamma * meta_monitor_manager_native_get_cached_crtc_gamma (MetaMonitorManagerNative *manager_native, - MetaCrtcKms *crtc_kms); - -#endif /* META_MONITOR_MANAGER_NATIVE_H */ diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c deleted file mode 100644 index 77e5309e1..000000000 --- a/src/backends/native/meta-onscreen-native.c +++ /dev/null @@ -1,2137 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016-2020 Red Hat - * Copyright (c) 2018,2019 DisplayLink (UK) Ltd. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include "config.h" - -#include "backends/native/meta-onscreen-native.h" - -#include <drm_fourcc.h> - -#include "backends/meta-egl-ext.h" -#include "backends/native/meta-cogl-utils.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-drm-buffer-dumb.h" -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-drm-buffer-import.h" -#include "backends/native/meta-drm-buffer.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-output-kms.h" -#include "backends/native/meta-renderer-native-gles3.h" -#include "backends/native/meta-renderer-native-private.h" - -typedef enum _MetaSharedFramebufferImportStatus -{ - /* Not tried importing yet. */ - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE, - /* Tried before and failed. */ - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_FAILED, - /* Tried before and succeeded. */ - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_OK -} MetaSharedFramebufferImportStatus; - -typedef struct _MetaOnscreenNativeSecondaryGpuState -{ - MetaGpuKms *gpu_kms; - MetaRendererNativeGpuData *renderer_gpu_data; - - EGLSurface egl_surface; - - struct { - struct gbm_surface *surface; - MetaDrmBuffer *current_fb; - MetaDrmBuffer *next_fb; - } gbm; - - struct { - MetaDrmBufferDumb *current_dumb_fb; - MetaDrmBufferDumb *dumb_fbs[2]; - } cpu; - - gboolean noted_primary_gpu_copy_ok; - gboolean noted_primary_gpu_copy_failed; - MetaSharedFramebufferImportStatus import_status; -} MetaOnscreenNativeSecondaryGpuState; - -struct _MetaOnscreenNative -{ - CoglOnscreenEgl parent; - - MetaRendererNative *renderer_native; - MetaGpuKms *render_gpu; - MetaOutput *output; - MetaCrtc *crtc; - - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - struct { - struct gbm_surface *surface; - MetaDrmBuffer *current_fb; - MetaDrmBuffer *next_fb; - } gbm; - -#ifdef HAVE_EGL_DEVICE - struct { - EGLStreamKHR stream; - - MetaDrmBufferDumb *dumb_fb; - } egl; -#endif - - MetaRendererView *view; -}; - -G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, - COGL_TYPE_ONSCREEN_EGL) - -static gboolean -init_secondary_gpu_state (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen, - GError **error); - -static void -swap_secondary_drm_fb (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - secondary_gpu_state = onscreen_native->secondary_gpu_state; - if (!secondary_gpu_state) - return; - - g_set_object (&secondary_gpu_state->gbm.current_fb, - secondary_gpu_state->gbm.next_fb); - g_clear_object (&secondary_gpu_state->gbm.next_fb); -} - -static void -free_current_secondary_bo (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - secondary_gpu_state = onscreen_native->secondary_gpu_state; - if (!secondary_gpu_state) - return; - - g_clear_object (&secondary_gpu_state->gbm.current_fb); -} - -static void -free_current_bo (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - - g_clear_object (&onscreen_native->gbm.current_fb); - free_current_secondary_bo (onscreen); -} - -static void -meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - - if (!onscreen_native->gbm.next_fb) - return; - - free_current_bo (onscreen); - - g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb); - g_clear_object (&onscreen_native->gbm.next_fb); - - swap_secondary_drm_fb (onscreen); -} - -static void -maybe_update_frame_info (MetaCrtc *crtc, - CoglFrameInfo *frame_info, - int64_t time_us, - CoglFrameInfoFlag flags, - unsigned int sequence) -{ - const MetaCrtcConfig *crtc_config; - const MetaCrtcModeInfo *crtc_mode_info; - float refresh_rate; - - g_return_if_fail (crtc); - - crtc_config = meta_crtc_get_config (crtc); - if (!crtc_config) - return; - - crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); - refresh_rate = crtc_mode_info->refresh_rate; - if (refresh_rate >= frame_info->refresh_rate) - { - frame_info->presentation_time_us = time_us; - frame_info->refresh_rate = refresh_rate; - frame_info->flags |= flags; - frame_info->sequence = sequence; - } -} - -static void -meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) -{ - CoglFrameInfo *info; - - info = cogl_onscreen_pop_head_frame_info (onscreen); - - g_assert (!cogl_onscreen_peek_head_frame_info (onscreen)); - - _cogl_onscreen_notify_frame_sync (onscreen, info); - _cogl_onscreen_notify_complete (onscreen, info); - cogl_object_unref (info); -} - -static void -notify_view_crtc_presented (MetaRendererView *view, - MetaKmsCrtc *kms_crtc, - int64_t time_us, - CoglFrameInfoFlag flags, - unsigned int sequence) -{ - ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view); - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (stage_view); - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - CoglFrameInfo *frame_info; - MetaCrtc *crtc; - - frame_info = cogl_onscreen_peek_head_frame_info (onscreen); - - crtc = META_CRTC (meta_crtc_kms_from_kms_crtc (kms_crtc)); - maybe_update_frame_info (crtc, frame_info, time_us, flags, sequence); - - meta_onscreen_native_notify_frame_complete (onscreen); - meta_onscreen_native_swap_drm_fb (onscreen); -} - -static int64_t -timeval_to_microseconds (const struct timeval *tv) -{ - return ((int64_t) tv->tv_sec) * G_USEC_PER_SEC + tv->tv_usec; -} - -static void -page_flip_feedback_flipped (MetaKmsCrtc *kms_crtc, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - gpointer user_data) -{ - MetaRendererView *view = user_data; - struct timeval page_flip_time; - MetaKmsDevice *kms_device; - int64_t presentation_time_us; - CoglFrameInfoFlag flags = COGL_FRAME_INFO_FLAG_VSYNC; - - page_flip_time = (struct timeval) { - .tv_sec = tv_sec, - .tv_usec = tv_usec, - }; - - kms_device = meta_kms_crtc_get_device (kms_crtc); - if (meta_kms_device_uses_monotonic_clock (kms_device)) - { - presentation_time_us = timeval_to_microseconds (&page_flip_time); - flags |= COGL_FRAME_INFO_FLAG_HW_CLOCK; - } - else - { - /* - * Other parts of the code assume MONOTONIC timestamps. So, if the device - * timestamp isn't MONOTONIC, don't use it. - */ - presentation_time_us = g_get_monotonic_time (); - } - - notify_view_crtc_presented (view, kms_crtc, - presentation_time_us, - flags, - sequence); -} - -static void -page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, - gpointer user_data) -{ - MetaRendererView *view = user_data; - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - CoglFrameInfo *frame_info; - - frame_info = cogl_onscreen_peek_head_frame_info (onscreen); - frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - - meta_onscreen_native_notify_frame_complete (onscreen); -} - -static void -page_flip_feedback_mode_set_fallback (MetaKmsCrtc *kms_crtc, - gpointer user_data) -{ - MetaRendererView *view = user_data; - int64_t now_us; - - /* - * We ended up not page flipping, thus we don't have a presentation time to - * use. Lets use the next best thing: the current time. - */ - - now_us = g_get_monotonic_time (); - - notify_view_crtc_presented (view, - kms_crtc, - now_us, - COGL_FRAME_INFO_FLAG_NONE, - 0); -} - -static void -page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, - gpointer user_data, - const GError *error) -{ - MetaRendererView *view = user_data; - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - CoglFrameInfo *frame_info; - - /* - * Page flipping failed, but we want to fail gracefully, so to avoid freezing - * the frame clock, emit a symbolic flip. - */ - - if (error && - !g_error_matches (error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Page flip discarded: %s", error->message); - - frame_info = cogl_onscreen_peek_head_frame_info (onscreen); - frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - - meta_onscreen_native_notify_frame_complete (onscreen); - meta_onscreen_native_swap_drm_fb (onscreen); -} - -static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = { - .flipped = page_flip_feedback_flipped, - .ready = page_flip_feedback_ready, - .mode_set_fallback = page_flip_feedback_mode_set_fallback, - .discarded = page_flip_feedback_discarded, -}; - -static MetaEgl * -meta_onscreen_native_get_egl (MetaOnscreenNative *onscreen_native) -{ - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - - return meta_renderer_native_get_egl (renderer_native); -} - -#ifdef HAVE_EGL_DEVICE -static int -custom_egl_stream_page_flip (gpointer custom_page_flip_data, - gpointer user_data) -{ - CoglOnscreen *onscreen = custom_page_flip_data; - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererView *view = user_data; - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - MetaRendererNativeGpuData *renderer_gpu_data; - EGLDisplay *egl_display; - EGLAttrib *acquire_attribs; - g_autoptr (GError) error = NULL; - - acquire_attribs = (EGLAttrib[]) { - EGL_DRM_FLIP_EVENT_DATA_NV, - (EGLAttrib) view, - EGL_NONE - }; - - renderer_gpu_data = - meta_renderer_native_get_gpu_data (onscreen_native->renderer_native, - onscreen_native->render_gpu); - - egl_display = renderer_gpu_data->egl_display; - if (!meta_egl_stream_consumer_acquire_attrib (egl, - egl_display, - onscreen_native->egl.stream, - acquire_attribs, - &error)) - { - if (g_error_matches (error, META_EGL_ERROR, EGL_RESOURCE_BUSY_EXT)) - return -EBUSY; - else - return -EINVAL; - } - - return 0; -} -#endif /* HAVE_EGL_DEVICE */ - -void -meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen) -{ - CoglFrameInfo *frame_info; - - meta_onscreen_native_swap_drm_fb (onscreen); - - frame_info = cogl_onscreen_peek_tail_frame_info (onscreen); - frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - meta_onscreen_native_notify_frame_complete (onscreen); -} - -static void -meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, - MetaRendererView *view, - MetaCrtc *crtc, - MetaKmsPageFlipListenerFlag flags) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaGpuKms *render_gpu = onscreen_native->render_gpu; - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - MetaRendererNativeGpuData *renderer_gpu_data; - MetaGpuKms *gpu_kms; - MetaKmsDevice *kms_device; - MetaKms *kms; - MetaKmsUpdate *kms_update; - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state = NULL; - MetaDrmBuffer *buffer; - - COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs, - "Onscreen (flip CRTCs)"); - - gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - kms = meta_kms_device_get_kms (kms_device); - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - - g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc)); - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - render_gpu); - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - if (gpu_kms == render_gpu) - { - buffer = onscreen_native->gbm.next_fb; - } - else - { - secondary_gpu_state = onscreen_native->secondary_gpu_state; - buffer = secondary_gpu_state->gbm.next_fb; - } - - meta_crtc_kms_assign_primary_plane (crtc_kms, buffer, kms_update); - - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - meta_kms_update_set_custom_page_flip (kms_update, - custom_egl_stream_page_flip, - onscreen_native); - break; -#endif - } - - meta_kms_update_add_page_flip_listener (kms_update, - kms_crtc, - &page_flip_listener_vtable, - flags, - g_object_ref (view), - g_object_unref); -} - -static void -meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, - MetaRendererNativeGpuData *renderer_gpu_data) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); - MetaKms *kms = meta_kms_device_get_kms (kms_device); - MetaKmsUpdate *kms_update; - - COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeSetCrtcModes, - "Onscreen (set CRTC modes)"); - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - { - MetaDrmBuffer *buffer; - - buffer = META_DRM_BUFFER (onscreen_native->egl.dumb_fb); - meta_crtc_kms_assign_primary_plane (crtc_kms, buffer, kms_update); - break; - } -#endif - } - - meta_crtc_kms_set_mode (crtc_kms, kms_update); - meta_output_kms_set_underscan (META_OUTPUT_KMS (onscreen_native->output), - kms_update); -} - -static void -secondary_gpu_release_dumb (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) -{ - unsigned i; - - for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++) - g_clear_object (&secondary_gpu_state->cpu.dumb_fbs[i]); -} - -static void -secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) -{ - MetaGpu *gpu = META_GPU (secondary_gpu_state->gpu_kms); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaEgl *egl = meta_backend_get_egl (backend); - - if (secondary_gpu_state->egl_surface != EGL_NO_SURFACE) - { - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = secondary_gpu_state->renderer_gpu_data; - meta_egl_destroy_surface (egl, - renderer_gpu_data->egl_display, - secondary_gpu_state->egl_surface, - NULL); - } - - g_clear_object (&secondary_gpu_state->gbm.current_fb); - g_clear_object (&secondary_gpu_state->gbm.next_fb); - g_clear_pointer (&secondary_gpu_state->gbm.surface, gbm_surface_destroy); - - secondary_gpu_release_dumb (secondary_gpu_state); - - g_free (secondary_gpu_state); -} - -static gboolean -import_shared_framebuffer (CoglOnscreen *onscreen, - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaGpuKms *gpu_kms; - MetaDeviceFile *device_file; - struct gbm_device *gbm_device; - MetaDrmBufferGbm *buffer_gbm; - MetaDrmBufferImport *buffer_import; - g_autoptr (GError) error = NULL; - - buffer_gbm = META_DRM_BUFFER_GBM (onscreen_native->gbm.next_fb); - - gpu_kms = secondary_gpu_state->gpu_kms; - device_file = secondary_gpu_state->renderer_gpu_data->device_file; - gbm_device = meta_gbm_device_from_gpu (gpu_kms); - buffer_import = meta_drm_buffer_import_new (device_file, - gbm_device, - buffer_gbm, - &error); - if (!buffer_import) - { - meta_topic (META_DEBUG_KMS, - "Zero-copy disabled for %s, " - "meta_drm_buffer_import_new failed: %s", - meta_device_file_get_path (device_file), - error->message); - - g_warn_if_fail (secondary_gpu_state->import_status == - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE); - - /* - * Fall back. If META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE is - * in effect, we have COPY_MODE_PRIMARY prepared already, so we - * simply retry with that path. Import status cannot be FAILED, - * because we should not retry if failed once. - * - * If import status is OK, that is unexpected and we do not - * have the fallback path prepared which means this output cannot - * work anymore. - */ - secondary_gpu_state->renderer_gpu_data->secondary.copy_mode = - META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY; - - secondary_gpu_state->import_status = - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_FAILED; - return FALSE; - } - - /* - * next_fb may already contain a fallback buffer, so clear it only - * when we are sure to succeed. - */ - g_clear_object (&secondary_gpu_state->gbm.next_fb); - secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_import); - - if (secondary_gpu_state->import_status == - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE) - { - /* - * Clean up the cpu-copy part of - * init_secondary_gpu_state_cpu_copy_mode () - */ - secondary_gpu_release_dumb (secondary_gpu_state); - - meta_topic (META_DEBUG_KMS, - "Using zero-copy for %s succeeded once.", - meta_device_file_get_path (device_file)); - } - - secondary_gpu_state->import_status = - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_OK; - return TRUE; -} - -static void -copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, - MetaRendererNativeGpuData *renderer_gpu_data, - gboolean *egl_context_changed) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - MetaGles3 *gles3 = meta_renderer_native_get_gles3 (renderer_native); - GError *error = NULL; - gboolean use_modifiers; - MetaDeviceFile *device_file; - MetaDrmBufferGbm *buffer_gbm; - struct gbm_bo *bo; - - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, - "FB Copy (secondary GPU)"); - - g_warn_if_fail (secondary_gpu_state->gbm.next_fb == NULL); - g_clear_object (&secondary_gpu_state->gbm.next_fb); - - if (!meta_egl_make_current (egl, - renderer_gpu_data->egl_display, - secondary_gpu_state->egl_surface, - secondary_gpu_state->egl_surface, - renderer_gpu_data->secondary.egl_context, - &error)) - { - g_warning ("Failed to make current: %s", error->message); - g_error_free (error); - return; - } - - *egl_context_changed = TRUE; - - - buffer_gbm = META_DRM_BUFFER_GBM (onscreen_native->gbm.next_fb); - bo = meta_drm_buffer_gbm_get_bo (buffer_gbm); - if (!meta_renderer_native_gles3_blit_shared_bo (egl, - gles3, - renderer_gpu_data->egl_display, - renderer_gpu_data->secondary.egl_context, - secondary_gpu_state->egl_surface, - bo, - &error)) - { - g_warning ("Failed to blit shared framebuffer: %s", error->message); - g_error_free (error); - return; - } - - if (!meta_egl_swap_buffers (egl, - renderer_gpu_data->egl_display, - secondary_gpu_state->egl_surface, - &error)) - { - g_warning ("Failed to swap buffers: %s", error->message); - g_error_free (error); - return; - } - - use_modifiers = meta_renderer_native_use_modifiers (renderer_native); - device_file = secondary_gpu_state->renderer_gpu_data->device_file; - buffer_gbm = - meta_drm_buffer_gbm_new_lock_front (device_file, - secondary_gpu_state->gbm.surface, - use_modifiers, - &error); - if (!buffer_gbm) - { - g_warning ("meta_drm_buffer_gbm_new_lock_front failed: %s", - error->message); - g_error_free (error); - return; - } - - secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_gbm); -} - -static MetaDrmBufferDumb * -secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) -{ - MetaDrmBufferDumb *current_dumb_fb; - - current_dumb_fb = secondary_gpu_state->cpu.current_dumb_fb; - if (current_dumb_fb == secondary_gpu_state->cpu.dumb_fbs[0]) - return secondary_gpu_state->cpu.dumb_fbs[1]; - else - return secondary_gpu_state->cpu.dumb_fbs[0]; -} - -static gboolean -copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscreen, - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaGpuKms *primary_gpu; - MetaRendererNativeGpuData *primary_gpu_data; - MetaDrmBufferDumb *buffer_dumb; - MetaDrmBuffer *buffer; - int width, height, stride; - uint32_t drm_format; - CoglFramebuffer *dmabuf_fb; - int dmabuf_fd; - g_autoptr (GError) error = NULL; - CoglPixelFormat cogl_format; - int ret; - - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferPrimaryGpu, - "FB Copy (primary GPU)"); - - primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); - primary_gpu_data = - meta_renderer_native_get_gpu_data (renderer_native, primary_gpu); - if (!primary_gpu_data->secondary.has_EGL_EXT_image_dma_buf_import_modifiers) - return FALSE; - - buffer_dumb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state); - buffer = META_DRM_BUFFER (buffer_dumb); - - width = meta_drm_buffer_get_width (buffer); - height = meta_drm_buffer_get_height (buffer); - stride = meta_drm_buffer_get_stride (buffer); - drm_format = meta_drm_buffer_get_format (buffer); - - g_assert (cogl_framebuffer_get_width (framebuffer) == width); - g_assert (cogl_framebuffer_get_height (framebuffer) == height); - - ret = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); - g_assert (ret); - - dmabuf_fd = meta_drm_buffer_dumb_ensure_dmabuf_fd (buffer_dumb, &error); - if (!dmabuf_fd) - { - meta_topic (META_DEBUG_KMS, - "Failed to create DMA buffer: %s", error->message); - return FALSE; - } - - dmabuf_fb = - meta_renderer_native_create_dma_buf_framebuffer (renderer_native, - dmabuf_fd, - width, - height, - stride, - 0, DRM_FORMAT_MOD_LINEAR, - drm_format, - &error); - - if (error) - { - meta_topic (META_DEBUG_KMS, - "Failed to create DMA buffer for blitting: %s", - error->message); - return FALSE; - } - - if (!cogl_blit_framebuffer (framebuffer, COGL_FRAMEBUFFER (dmabuf_fb), - 0, 0, 0, 0, - width, height, - &error)) - { - g_object_unref (dmabuf_fb); - return FALSE; - } - - g_object_unref (dmabuf_fb); - - g_set_object (&secondary_gpu_state->gbm.next_fb, buffer); - secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb; - - return TRUE; -} - -static void -copy_shared_framebuffer_cpu (CoglOnscreen *onscreen, - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, - MetaRendererNativeGpuData *renderer_gpu_data) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - MetaDrmBufferDumb *buffer_dumb; - MetaDrmBuffer *buffer; - int width, height, stride; - uint32_t drm_format; - void *buffer_data; - CoglBitmap *dumb_bitmap; - CoglPixelFormat cogl_format; - gboolean ret; - - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferCpu, - "FB Copy (CPU)"); - - buffer_dumb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state); - buffer = META_DRM_BUFFER (buffer_dumb); - - width = meta_drm_buffer_get_width (buffer); - height = meta_drm_buffer_get_height (buffer); - stride = meta_drm_buffer_get_stride (buffer); - drm_format = meta_drm_buffer_get_format (buffer); - buffer_data = meta_drm_buffer_dumb_get_data (buffer_dumb); - - g_assert (cogl_framebuffer_get_width (framebuffer) == width); - g_assert (cogl_framebuffer_get_height (framebuffer) == height); - - ret = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); - g_assert (ret); - - dumb_bitmap = cogl_bitmap_new_for_data (cogl_context, - width, - height, - cogl_format, - stride, - buffer_data); - - if (!cogl_framebuffer_read_pixels_into_bitmap (framebuffer, - 0 /* x */, - 0 /* y */, - COGL_READ_PIXELS_COLOR_BUFFER, - dumb_bitmap)) - g_warning ("Failed to CPU-copy to a secondary GPU output"); - - cogl_object_unref (dumb_bitmap); - - g_clear_object (&secondary_gpu_state->gbm.next_fb); - secondary_gpu_state->gbm.next_fb = buffer; - secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb; -} - -static void -update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePreSwapBuffers, - "Onscreen (secondary gpu pre-swap-buffers)"); - - secondary_gpu_state = onscreen_native->secondary_gpu_state; - if (secondary_gpu_state) - { - MetaRendererNativeGpuData *renderer_gpu_data; - MetaDeviceFile *device_file; - - renderer_gpu_data = secondary_gpu_state->renderer_gpu_data; - device_file = renderer_gpu_data->device_file; - switch (renderer_gpu_data->secondary.copy_mode) - { - case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU: - /* Done after eglSwapBuffers. */ - break; - case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO: - /* Done after eglSwapBuffers. */ - if (secondary_gpu_state->import_status == - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_OK) - break; - /* prepare fallback */ - G_GNUC_FALLTHROUGH; - case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: - if (!copy_shared_framebuffer_primary_gpu (onscreen, - secondary_gpu_state)) - { - if (!secondary_gpu_state->noted_primary_gpu_copy_failed) - { - meta_topic (META_DEBUG_KMS, - "Using primary GPU to copy for %s failed once.", - meta_device_file_get_path (device_file)); - secondary_gpu_state->noted_primary_gpu_copy_failed = TRUE; - } - - copy_shared_framebuffer_cpu (onscreen, - secondary_gpu_state, - renderer_gpu_data); - } - else if (!secondary_gpu_state->noted_primary_gpu_copy_ok) - { - meta_topic (META_DEBUG_KMS, - "Using primary GPU to copy for %s succeeded once.", - meta_device_file_get_path (device_file)); - secondary_gpu_state->noted_primary_gpu_copy_ok = TRUE; - } - break; - } - } -} - -static void -update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen, - gboolean *egl_context_changed) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePostSwapBuffers, - "Onscreen (secondary gpu post-swap-buffers)"); - - secondary_gpu_state = onscreen_native->secondary_gpu_state; - if (secondary_gpu_state) - { - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = - meta_renderer_native_get_gpu_data (renderer_native, - secondary_gpu_state->gpu_kms); -retry: - switch (renderer_gpu_data->secondary.copy_mode) - { - case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO: - if (!import_shared_framebuffer (onscreen, - secondary_gpu_state)) - goto retry; - break; - case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU: - copy_shared_framebuffer_gpu (onscreen, - secondary_gpu_state, - renderer_gpu_data, - egl_context_changed); - break; - case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: - /* Done before eglSwapBuffers. */ - break; - } - } -} - -static void -ensure_crtc_modes (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - - if (meta_renderer_native_pop_pending_mode_set (renderer_native, - onscreen_native->view)) - meta_onscreen_native_set_crtc_mode (onscreen, renderer_gpu_data); -} - -static void -meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - const int *rectangles, - int n_rectangles, - CoglFrameInfo *frame_info, - gpointer user_data) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaGpuKms *render_gpu = onscreen_native->render_gpu; - MetaDeviceFile *render_device_file; - ClutterFrame *frame = user_data; - CoglOnscreenClass *parent_class; - gboolean egl_context_changed = FALSE; - gboolean use_modifiers; - MetaPowerSave power_save_mode; - g_autoptr (GError) error = NULL; - MetaDrmBufferGbm *buffer_gbm; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *feedback_error; - - COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers, - "Onscreen (swap-buffers)"); - - update_secondary_gpu_state_pre_swap_buffers (onscreen); - - parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class); - parent_class->swap_buffers_with_damage (onscreen, - rectangles, - n_rectangles, - frame_info, - user_data); - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - render_gpu); - render_device_file = renderer_gpu_data->device_file; - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - g_warn_if_fail (onscreen_native->gbm.next_fb == NULL); - g_clear_object (&onscreen_native->gbm.next_fb); - - use_modifiers = meta_renderer_native_use_modifiers (renderer_native); - buffer_gbm = - meta_drm_buffer_gbm_new_lock_front (render_device_file, - onscreen_native->gbm.surface, - use_modifiers, - &error); - if (!buffer_gbm) - { - g_warning ("Failed to lock front buffer on %s: %s", - meta_device_file_get_path (render_device_file), - error->message); - return; - } - - onscreen_native->gbm.next_fb = META_DRM_BUFFER (buffer_gbm); - - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - break; -#endif - } - - update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed); - - /* - * If we changed EGL context, cogl will have the wrong idea about what is - * current, making it fail to set it when it needs to. Avoid that by making - * EGL_NO_CONTEXT current now, making cogl eventually set the correct - * context. - */ - if (egl_context_changed) - _cogl_winsys_egl_ensure_current (cogl_display); - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode == META_POWER_SAVE_ON) - { - ensure_crtc_modes (onscreen); - meta_onscreen_native_flip_crtc (onscreen, - onscreen_native->view, - onscreen_native->crtc, - META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE); - } - else - { - meta_renderer_native_queue_power_save_page_flip (renderer_native, - onscreen); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - - COGL_TRACE_BEGIN_SCOPED (MetaRendererNativePostKmsUpdate, - "Onscreen (post pending update)"); - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); - kms_device = meta_kms_crtc_get_device (kms_crtc); - - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - if (meta_renderer_native_has_pending_mode_sets (renderer_native)) - { - meta_topic (META_DEBUG_KMS, - "Postponing primary plane composite update for CRTC %u (%s)", - meta_kms_crtc_get_id (kms_crtc), - meta_kms_device_get_path (kms_device)); - - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - else if (meta_renderer_native_has_pending_mode_set (renderer_native)) - { - meta_topic (META_DEBUG_KMS, "Posting global mode set updates on %s", - meta_kms_device_get_path (kms_device)); - - meta_renderer_native_notify_mode_sets_reset (renderer_native); - meta_renderer_native_post_mode_set_updates (renderer_native); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - if (meta_renderer_native_has_pending_mode_set (renderer_native)) - { - meta_renderer_native_notify_mode_sets_reset (renderer_native); - meta_renderer_native_post_mode_set_updates (renderer_native); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - break; -#endif - } - - meta_topic (META_DEBUG_KMS, - "Posting primary plane composite update for CRTC %u (%s)", - meta_kms_crtc_get_id (kms_crtc), - meta_kms_device_get_path (kms_device)); - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags); - - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - break; - case META_KMS_FEEDBACK_FAILED: - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - - feedback_error = meta_kms_feedback_get_error (kms_feedback); - if (!g_error_matches (feedback_error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", feedback_error->message); - break; - } -} - -gboolean -meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, - uint32_t drm_format, - uint64_t drm_modifier, - uint32_t stride) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - const MetaCrtcConfig *crtc_config; - MetaDrmBuffer *fb; - struct gbm_bo *gbm_bo; - - crtc_config = meta_crtc_get_config (onscreen_native->crtc); - if (crtc_config->transform != META_MONITOR_TRANSFORM_NORMAL) - return FALSE; - - if (onscreen_native->secondary_gpu_state) - return FALSE; - - if (!onscreen_native->gbm.surface) - return FALSE; - - fb = onscreen_native->gbm.current_fb ? onscreen_native->gbm.current_fb - : onscreen_native->gbm.next_fb; - if (!fb) - return FALSE; - - if (!META_IS_DRM_BUFFER_GBM (fb)) - return FALSE; - - gbm_bo = meta_drm_buffer_gbm_get_bo (META_DRM_BUFFER_GBM (fb)); - - if (gbm_bo_get_format (gbm_bo) != drm_format) - return FALSE; - - if (gbm_bo_get_modifier (gbm_bo) != drm_modifier) - return FALSE; - - if (gbm_bo_get_stride (gbm_bo) != stride) - return FALSE; - - return TRUE; -} - -static gboolean -meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, - CoglScanout *scanout, - CoglFrameInfo *frame_info, - gpointer user_data, - GError **error) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaGpuKms *render_gpu = onscreen_native->render_gpu; - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaPowerSave power_save_mode; - ClutterFrame *frame = user_data; - MetaDrmBuffer *scanout_buffer; - GError *fill_timings_error = NULL; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *feedback_error; - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode != META_POWER_SAVE_ON) - { - g_set_error_literal (error, - COGL_SCANOUT_ERROR, - COGL_SCANOUT_ERROR_INHIBITED, - "Direct scanout is inhibited during power saving mode"); - return FALSE; - } - - if (meta_renderer_native_has_pending_mode_set (renderer_native)) - { - g_set_error_literal (error, - COGL_SCANOUT_ERROR, - COGL_SCANOUT_ERROR_INHIBITED, - "Direct scanout is inhibited when a mode set is pending"); - return FALSE; - } - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - render_gpu); - - g_warn_if_fail (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_GBM); - g_warn_if_fail (!onscreen_native->gbm.next_fb); - - g_set_object (&onscreen_native->gbm.next_fb, META_DRM_BUFFER (scanout)); - - /* Try to get a measurement of GPU rendering time on the scanout buffer. - * - * The successful operation here adds ~0.4 ms to a ~0.1 ms total frame clock - * dispatch duration when displaying an unredirected client, thus - * unfortunately bringing it more in line with duration of the regular - * non-unredirected frame clock dispatch. However, measuring GPU rendering - * time is important for computing accurate max render time without - * underestimating. Also this operation should be optimizable by caching - * EGLImage for each buffer instead of re-creating it every time it's needed. - * This should also help all other cases which convert the buffer to a - * EGLImage. - */ - if (META_IS_DRM_BUFFER (scanout)) - { - scanout_buffer = META_DRM_BUFFER (scanout); - if (meta_drm_buffer_supports_fill_timings (scanout_buffer)) - { - if (!meta_drm_buffer_fill_timings (scanout_buffer, frame_info, - &fill_timings_error)) - { - g_warning ("Failed to fill timings for a scanout buffer: %s", - fill_timings_error->message); - g_error_free (fill_timings_error); - } - } - } - - ensure_crtc_modes (onscreen); - meta_onscreen_native_flip_crtc (onscreen, - onscreen_native->view, - onscreen_native->crtc, - META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR); - - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); - kms_device = meta_kms_crtc_get_device (kms_crtc); - - meta_topic (META_DEBUG_KMS, - "Posting direct scanout update for CRTC %u (%s)", - meta_kms_crtc_get_id (kms_crtc), - meta_kms_device_get_path (kms_device)); - - flags = META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR; - kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags); - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - break; - case META_KMS_FEEDBACK_FAILED: - feedback_error = meta_kms_feedback_get_error (kms_feedback); - - if (g_error_matches (feedback_error, - G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) - break; - - g_clear_object (&onscreen_native->gbm.next_fb); - g_propagate_error (error, g_error_copy (feedback_error)); - return FALSE; - } - - return TRUE; -} - -static void -add_onscreen_frame_info (MetaCrtc *crtc) -{ - MetaGpu *gpu = meta_crtc_get_gpu (crtc); - MetaBackend *backend = meta_gpu_get_backend (gpu); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - ClutterStageWindow *stage_window = _clutter_stage_get_window (stage); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererView *view = meta_renderer_get_view_for_crtc (renderer, crtc); - - meta_stage_impl_add_onscreen_frame_info (META_STAGE_IMPL (stage_window), - CLUTTER_STAGE_VIEW (view)); -} - -void -meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, - ClutterFrame *frame) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtc *crtc = onscreen_native->crtc; - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);; - MetaKms *kms = meta_kms_device_get_kms (kms_device); - MetaKmsUpdateFlag flags; - MetaKmsUpdate *kms_update; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *error; - - kms_update = meta_kms_get_pending_update (kms, kms_device); - if (!kms_update) - { - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); - return; - } - - meta_kms_update_add_page_flip_listener (kms_update, - kms_crtc, - &page_flip_listener_vtable, - META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE, - g_object_ref (onscreen_native->view), - g_object_unref); - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, - kms_device, - flags); - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - add_onscreen_frame_info (crtc); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - break; - case META_KMS_FEEDBACK_FAILED: - add_onscreen_frame_info (crtc); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - - error = meta_kms_feedback_get_error (kms_feedback); - if (!g_error_matches (error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", error->message); - break; - } -} - -static gboolean -should_surface_be_sharable (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - - if (META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)) == - onscreen_native->render_gpu) - return FALSE; - else - return TRUE; -} - -static uint32_t -get_gbm_format_from_egl (MetaEgl *egl, - EGLDisplay egl_display, - EGLConfig egl_config) -{ - uint32_t gbm_format; - EGLint native_visual_id; - - if (meta_egl_get_config_attrib (egl, - egl_display, - egl_config, - EGL_NATIVE_VISUAL_ID, - &native_visual_id, - NULL)) - gbm_format = (uint32_t) native_visual_id; - else - g_assert_not_reached (); - - return gbm_format; -} - -static GArray * -get_supported_kms_modifiers (MetaCrtcKms *crtc_kms, - uint32_t format) -{ - GArray *modifiers; - GArray *crtc_mods; - unsigned int i; - - crtc_mods = meta_crtc_kms_get_modifiers (crtc_kms, format); - if (!crtc_mods) - return NULL; - - modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t)); - - /* - * For each modifier from base_crtc, check if it's available on all other - * CRTCs. - */ - for (i = 0; i < crtc_mods->len; i++) - { - uint64_t modifier = g_array_index (crtc_mods, uint64_t, i); - - g_array_append_val (modifiers, modifier); - } - - if (modifiers->len == 0) - { - g_array_free (modifiers, TRUE); - return NULL; - } - - return modifiers; -} - -static GArray * -get_supported_egl_modifiers (CoglOnscreen *onscreen, - MetaCrtcKms *crtc_kms, - uint32_t format) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - MetaGpu *gpu; - MetaRendererNativeGpuData *renderer_gpu_data; - EGLint num_modifiers; - GArray *modifiers; - GError *error = NULL; - gboolean ret; - - gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms)); - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - META_GPU_KMS (gpu)); - - if (!meta_egl_has_extensions (egl, renderer_gpu_data->egl_display, NULL, - "EGL_EXT_image_dma_buf_import_modifiers", - NULL)) - return NULL; - - ret = meta_egl_query_dma_buf_modifiers (egl, renderer_gpu_data->egl_display, - format, 0, NULL, NULL, - &num_modifiers, NULL); - if (!ret || num_modifiers == 0) - return NULL; - - modifiers = g_array_sized_new (FALSE, FALSE, sizeof (uint64_t), - num_modifiers); - ret = meta_egl_query_dma_buf_modifiers (egl, renderer_gpu_data->egl_display, - format, num_modifiers, - (EGLuint64KHR *) modifiers->data, NULL, - &num_modifiers, &error); - - if (!ret) - { - g_warning ("Failed to query DMABUF modifiers: %s", error->message); - g_error_free (error); - g_array_free (modifiers, TRUE); - return NULL; - } - - return modifiers; -} - -static GArray * -get_supported_modifiers (CoglOnscreen *onscreen, - uint32_t format) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); - MetaGpu *gpu; - g_autoptr (GArray) modifiers = NULL; - - gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms)); - if (gpu == META_GPU (onscreen_native->render_gpu)) - modifiers = get_supported_kms_modifiers (crtc_kms, format); - else - modifiers = get_supported_egl_modifiers (onscreen, crtc_kms, format); - - return g_steal_pointer (&modifiers); -} - -static GArray * -get_supported_kms_formats (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); - - return meta_crtc_kms_copy_drm_format_list (crtc_kms); -} - -static gboolean -create_surfaces_gbm (CoglOnscreen *onscreen, - int width, - int height, - struct gbm_surface **gbm_surface, - EGLSurface *egl_surface, - GError **error) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglDisplay *cogl_display = cogl_context->display; - CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - struct gbm_surface *new_gbm_surface = NULL; - EGLNativeWindowType egl_native_window; - EGLSurface new_egl_surface; - uint32_t format; - GArray *modifiers; - - renderer_gpu_data = - meta_renderer_native_get_gpu_data (renderer_native, - onscreen_native->render_gpu); - - format = get_gbm_format_from_egl (egl, - cogl_renderer_egl->edpy, - cogl_display_egl->egl_config); - - if (meta_renderer_native_use_modifiers (renderer_native)) - modifiers = get_supported_modifiers (onscreen, format); - else - modifiers = NULL; - - if (modifiers) - { - new_gbm_surface = - gbm_surface_create_with_modifiers (renderer_gpu_data->gbm.device, - width, height, format, - (uint64_t *) modifiers->data, - modifiers->len); - g_array_free (modifiers, TRUE); - } - - if (!new_gbm_surface) - { - uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; - - if (should_surface_be_sharable (onscreen)) - flags |= GBM_BO_USE_LINEAR; - - new_gbm_surface = gbm_surface_create (renderer_gpu_data->gbm.device, - width, height, - format, - flags); - } - - if (!new_gbm_surface) - { - g_set_error (error, COGL_WINSYS_ERROR, - COGL_WINSYS_ERROR_CREATE_ONSCREEN, - "Failed to allocate surface"); - return FALSE; - } - - egl_native_window = (EGLNativeWindowType) new_gbm_surface; - new_egl_surface = - meta_egl_create_window_surface (egl, - cogl_renderer_egl->edpy, - cogl_display_egl->egl_config, - egl_native_window, - NULL, - error); - if (new_egl_surface == EGL_NO_SURFACE) - { - gbm_surface_destroy (new_gbm_surface); - return FALSE; - } - - *gbm_surface = new_gbm_surface; - *egl_surface = new_egl_surface; - - return TRUE; -} - -#ifdef HAVE_EGL_DEVICE -static gboolean -create_surfaces_egl_device (CoglOnscreen *onscreen, - int width, - int height, - EGLStreamKHR *out_egl_stream, - EGLSurface *out_egl_surface, - GError **error) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglDisplay *cogl_display = cogl_context->display; - CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaEgl *egl = - meta_renderer_native_get_egl (renderer_gpu_data->renderer_native); - EGLDisplay egl_display = renderer_gpu_data->egl_display; - EGLConfig egl_config; - EGLStreamKHR egl_stream; - EGLSurface egl_surface; - EGLint num_layers; - EGLOutputLayerEXT output_layer; - EGLAttrib output_attribs[3]; - EGLint stream_attribs[] = { - EGL_STREAM_FIFO_LENGTH_KHR, 0, - EGL_CONSUMER_AUTO_ACQUIRE_EXT, EGL_FALSE, - EGL_NONE - }; - EGLint stream_producer_attribs[] = { - EGL_WIDTH, width, - EGL_HEIGHT, height, - EGL_NONE - }; - - egl_stream = meta_egl_create_stream (egl, egl_display, stream_attribs, error); - if (egl_stream == EGL_NO_STREAM_KHR) - return FALSE; - - output_attribs[0] = EGL_DRM_CRTC_EXT; - output_attribs[1] = meta_crtc_get_id (onscreen_native->crtc); - output_attribs[2] = EGL_NONE; - - if (!meta_egl_get_output_layers (egl, egl_display, - output_attribs, - &output_layer, 1, &num_layers, - error)) - { - meta_egl_destroy_stream (egl, egl_display, egl_stream, NULL); - return FALSE; - } - - if (num_layers < 1) - { - meta_egl_destroy_stream (egl, egl_display, egl_stream, NULL); - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Unable to find output layers."); - return FALSE; - } - - if (!meta_egl_stream_consumer_output (egl, egl_display, - egl_stream, output_layer, - error)) - { - meta_egl_destroy_stream (egl, egl_display, egl_stream, NULL); - return FALSE; - } - - egl_config = cogl_display_egl->egl_config; - egl_surface = meta_egl_create_stream_producer_surface (egl, - egl_display, - egl_config, - egl_stream, - stream_producer_attribs, - error); - if (egl_surface == EGL_NO_SURFACE) - { - meta_egl_destroy_stream (egl, egl_display, egl_stream, NULL); - return FALSE; - } - - *out_egl_stream = egl_stream; - *out_egl_surface = egl_surface; - - return TRUE; -} -#endif /* HAVE_EGL_DEVICE */ - -void -meta_onscreen_native_set_view (CoglOnscreen *onscreen, - MetaRendererView *view) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - onscreen_native->view = view; -} - -static gboolean -meta_onscreen_native_allocate (CoglFramebuffer *framebuffer, - GError **error) -{ - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen); - MetaRendererNativeGpuData *renderer_gpu_data; - struct gbm_surface *gbm_surface; - EGLSurface egl_surface; - int width; - int height; -#ifdef HAVE_EGL_DEVICE - MetaDeviceFile *render_device_file; - EGLStreamKHR egl_stream; -#endif - CoglFramebufferClass *parent_class; - - if (META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)) != - onscreen_native->render_gpu) - { - if (!init_secondary_gpu_state (onscreen_native->renderer_native, - onscreen, error)) - return FALSE; - } - - width = cogl_framebuffer_get_width (framebuffer); - height = cogl_framebuffer_get_height (framebuffer); - - renderer_gpu_data = - meta_renderer_native_get_gpu_data (onscreen_native->renderer_native, - onscreen_native->render_gpu); - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - if (!create_surfaces_gbm (onscreen, - width, height, - &gbm_surface, - &egl_surface, - error)) - return FALSE; - - onscreen_native->gbm.surface = gbm_surface; - cogl_onscreen_egl_set_egl_surface (onscreen_egl, egl_surface); - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - render_device_file = renderer_gpu_data->device_file; - onscreen_native->egl.dumb_fb = - meta_drm_buffer_dumb_new (render_device_file, - width, height, - DRM_FORMAT_XRGB8888, - error); - if (!onscreen_native->egl.dumb_fb) - return FALSE; - - if (!create_surfaces_egl_device (onscreen, - width, height, - &egl_stream, - &egl_surface, - error)) - return FALSE; - - onscreen_native->egl.stream = egl_stream; - cogl_onscreen_egl_set_egl_surface (onscreen_egl, egl_surface); - break; -#endif /* HAVE_EGL_DEVICE */ - } - - parent_class = COGL_FRAMEBUFFER_CLASS (meta_onscreen_native_parent_class); - return parent_class->allocate (framebuffer, error); -} - -static gboolean -init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen, - MetaRendererNativeGpuData *renderer_gpu_data, - GError **error) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - int width, height; - EGLNativeWindowType egl_native_window; - struct gbm_surface *gbm_surface; - EGLSurface egl_surface; - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - MetaGpuKms *gpu_kms; - uint32_t format; - - width = cogl_framebuffer_get_width (framebuffer); - height = cogl_framebuffer_get_height (framebuffer); - format = get_gbm_format_from_egl (egl, - renderer_gpu_data->egl_display, - renderer_gpu_data->secondary.egl_config); - - gbm_surface = gbm_surface_create (renderer_gpu_data->gbm.device, - width, height, - format, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - if (!gbm_surface) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to create gbm_surface: %s", strerror (errno)); - return FALSE; - } - - egl_native_window = (EGLNativeWindowType) gbm_surface; - egl_surface = - meta_egl_create_window_surface (egl, - renderer_gpu_data->egl_display, - renderer_gpu_data->secondary.egl_config, - egl_native_window, - NULL, - error); - if (egl_surface == EGL_NO_SURFACE) - { - gbm_surface_destroy (gbm_surface); - return FALSE; - } - - secondary_gpu_state = g_new0 (MetaOnscreenNativeSecondaryGpuState, 1); - - gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)); - secondary_gpu_state->gpu_kms = gpu_kms; - secondary_gpu_state->renderer_gpu_data = renderer_gpu_data; - secondary_gpu_state->gbm.surface = gbm_surface; - secondary_gpu_state->egl_surface = egl_surface; - - onscreen_native->secondary_gpu_state = secondary_gpu_state; - - return TRUE; -} - -static uint32_t -pick_secondary_gpu_framebuffer_format_for_cpu (CoglOnscreen *onscreen) -{ - /* - * cogl_framebuffer_read_pixels_into_bitmap () supported formats in - * preference order. Ideally these should depend on the render buffer - * format copy_shared_framebuffer_cpu () will be reading from but - * alpha channel ignored. - */ - static const uint32_t preferred_formats[] = - { - /* - * DRM_FORMAT_XBGR8888 a.k.a GL_RGBA, GL_UNSIGNED_BYTE on - * little-endian is possibly the most optimized glReadPixels - * output format. glReadPixels cannot avoid manufacturing an alpha - * channel if the render buffer does not have one and converting - * to ABGR8888 may be more optimized than ARGB8888. - */ - DRM_FORMAT_XBGR8888, - /* The rest are other fairly commonly used formats in OpenGL. */ - DRM_FORMAT_XRGB8888, - }; - g_autoptr (GArray) formats = NULL; - size_t k; - unsigned int i; - uint32_t drm_format; - - formats = get_supported_kms_formats (onscreen); - - /* Check if any of our preferred formats are supported. */ - for (k = 0; k < G_N_ELEMENTS (preferred_formats); k++) - { - g_assert (meta_cogl_pixel_format_from_drm_format (preferred_formats[k], - NULL, - NULL)); - - for (i = 0; i < formats->len; i++) - { - drm_format = g_array_index (formats, uint32_t, i); - - if (drm_format == preferred_formats[k]) - return drm_format; - } - } - - /* - * Otherwise just pick an arbitrary format we recognize. The formats - * list is not in any specific order and we don't know any better - * either. - */ - for (i = 0; i < formats->len; i++) - { - drm_format = g_array_index (formats, uint32_t, i); - - if (meta_cogl_pixel_format_from_drm_format (drm_format, NULL, NULL)) - return drm_format; - } - - return DRM_FORMAT_INVALID; -} - -static gboolean -init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen, - MetaRendererNativeGpuData *renderer_gpu_data, - GError **error) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - MetaGpuKms *gpu_kms; - MetaDeviceFile *device_file; - int width, height; - unsigned int i; - uint32_t drm_format; - MetaDrmFormatBuf tmp; - - drm_format = pick_secondary_gpu_framebuffer_format_for_cpu (onscreen); - if (drm_format == DRM_FORMAT_INVALID) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Could not find a suitable pixel format in CPU copy mode"); - return FALSE; - } - - width = cogl_framebuffer_get_width (framebuffer); - height = cogl_framebuffer_get_height (framebuffer); - - gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)); - device_file = renderer_gpu_data->device_file; - meta_topic (META_DEBUG_KMS, - "Secondary GPU %s using DRM format '%s' (0x%x) for a %dx%d output.", - meta_device_file_get_path (device_file), - meta_drm_format_to_string (&tmp, drm_format), - drm_format, - width, height); - - secondary_gpu_state = g_new0 (MetaOnscreenNativeSecondaryGpuState, 1); - secondary_gpu_state->renderer_gpu_data = renderer_gpu_data; - secondary_gpu_state->gpu_kms = gpu_kms; - secondary_gpu_state->egl_surface = EGL_NO_SURFACE; - - for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++) - { - secondary_gpu_state->cpu.dumb_fbs[i] = - meta_drm_buffer_dumb_new (device_file, - width, height, - drm_format, - error); - if (!secondary_gpu_state->cpu.dumb_fbs[i]) - { - secondary_gpu_state_free (secondary_gpu_state); - return FALSE; - } - } - - /* - * This function initializes everything needed for - * META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO as well. - */ - secondary_gpu_state->import_status = - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE; - - onscreen_native->secondary_gpu_state = secondary_gpu_state; - - return TRUE; -} - -static gboolean -init_secondary_gpu_state (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen, - GError **error) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaGpu *gpu = meta_crtc_get_gpu (onscreen_native->crtc); - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - META_GPU_KMS (gpu)); - - switch (renderer_gpu_data->secondary.copy_mode) - { - case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU: - if (!init_secondary_gpu_state_gpu_copy_mode (renderer_native, - onscreen, - renderer_gpu_data, - error)) - return FALSE; - break; - case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO: - /* - * Initialize also the primary copy mode, so that if zero-copy - * path fails, which is quite likely, we can simply continue - * with the primary copy path on the very first frame. - */ - G_GNUC_FALLTHROUGH; - case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: - if (!init_secondary_gpu_state_cpu_copy_mode (renderer_native, - onscreen, - renderer_gpu_data, - error)) - return FALSE; - break; - } - - return TRUE; -} - -MetaOnscreenNative * -meta_onscreen_native_new (MetaRendererNative *renderer_native, - MetaGpuKms *render_gpu, - MetaOutput *output, - MetaCrtc *crtc, - CoglContext *cogl_context, - int width, - int height) -{ - MetaOnscreenNative *onscreen_native; - CoglFramebufferDriverConfig driver_config; - - driver_config = (CoglFramebufferDriverConfig) { - .type = COGL_FRAMEBUFFER_DRIVER_TYPE_BACK, - }; - onscreen_native = g_object_new (META_TYPE_ONSCREEN_NATIVE, - "context", cogl_context, - "driver-config", &driver_config, - "width", width, - "height", height, - NULL); - - onscreen_native->renderer_native = renderer_native; - onscreen_native->render_gpu = render_gpu; - onscreen_native->output = output; - onscreen_native->crtc = crtc; - - return onscreen_native; -} - -static void -meta_onscreen_native_dispose (GObject *object) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (object); - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = - meta_renderer_native_get_gpu_data (renderer_native, - onscreen_native->render_gpu); - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - /* flip state takes a reference on the onscreen so there should - * never be outstanding flips when we reach here. */ - g_warn_if_fail (onscreen_native->gbm.next_fb == NULL); - - free_current_bo (onscreen); - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - g_clear_object (&onscreen_native->egl.dumb_fb); - - if (onscreen_native->egl.stream != EGL_NO_STREAM_KHR) - { - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - - meta_egl_destroy_stream (egl, - cogl_renderer_egl->edpy, - onscreen_native->egl.stream, - NULL); - onscreen_native->egl.stream = EGL_NO_STREAM_KHR; - } - break; -#endif /* HAVE_EGL_DEVICE */ - } - - G_OBJECT_CLASS (meta_onscreen_native_parent_class)->dispose (object); - - g_clear_pointer (&onscreen_native->gbm.surface, gbm_surface_destroy); - g_clear_pointer (&onscreen_native->secondary_gpu_state, - secondary_gpu_state_free); -} - -static void -meta_onscreen_native_init (MetaOnscreenNative *onscreen_native) -{ -} - -static void -meta_onscreen_native_class_init (MetaOnscreenNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - CoglFramebufferClass *framebuffer_class = COGL_FRAMEBUFFER_CLASS (klass); - CoglOnscreenClass *onscreen_class = COGL_ONSCREEN_CLASS (klass); - - object_class->dispose = meta_onscreen_native_dispose; - - framebuffer_class->allocate = meta_onscreen_native_allocate; - - onscreen_class->swap_buffers_with_damage = - meta_onscreen_native_swap_buffers_with_damage; - onscreen_class->direct_scanout = meta_onscreen_native_direct_scanout; -} diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h deleted file mode 100644 index 020fc8a14..000000000 --- a/src/backends/native/meta-onscreen-native.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2016-2020 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. - * - */ - -#ifndef META_ONSCREEN_NATIVE_H -#define META_ONSCREEN_NATIVE_H - -#include <glib.h> - -#include "backends/meta-backend-types.h" -#include "backends/native/meta-backend-native-types.h" -#include "clutter/clutter.h" -#include "cogl/cogl.h" - -#define META_TYPE_ONSCREEN_NATIVE (meta_onscreen_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaOnscreenNative, meta_onscreen_native, - META, ONSCREEN_NATIVE, - CoglOnscreenEgl) - -void meta_renderer_native_release_onscreen (CoglOnscreen *onscreen); - -void meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, - ClutterFrame *frame); - -void meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen); - -gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, - uint32_t drm_format, - uint64_t drm_modifier, - uint32_t stride); - -void meta_onscreen_native_set_view (CoglOnscreen *onscreen, - MetaRendererView *view); - -MetaOnscreenNative * meta_onscreen_native_new (MetaRendererNative *renderer_native, - MetaGpuKms *render_gpu, - MetaOutput *output, - MetaCrtc *crtc, - CoglContext *cogl_context, - int width, - int height); - -#endif /* META_ONSCREEN_NATIVE_H */ diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c deleted file mode 100644 index f35cdf04e..000000000 --- a/src/backends/native/meta-output-kms.c +++ /dev/null @@ -1,414 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013-2017 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-output-kms.h" - -#include <errno.h> -#include <stdlib.h> -#include <string.h> - -#include "backends/meta-crtc.h" -#include "backends/native/meta-kms-connector.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-mode.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-crtc-mode-kms.h" - -#define SYNC_TOLERANCE 0.01 /* 1 percent */ - -struct _MetaOutputKms -{ - MetaOutputNative parent; - - MetaKmsConnector *kms_connector; -}; - -G_DEFINE_TYPE (MetaOutputKms, meta_output_kms, META_TYPE_OUTPUT_NATIVE) - -MetaKmsConnector * -meta_output_kms_get_kms_connector (MetaOutputKms *output_kms) -{ - return output_kms->kms_connector; -} - -void -meta_output_kms_set_underscan (MetaOutputKms *output_kms, - MetaKmsUpdate *kms_update) -{ - MetaOutput *output = META_OUTPUT (output_kms); - const MetaOutputInfo *output_info = meta_output_get_info (output); - - if (!output_info->supports_underscanning) - return; - - if (meta_output_is_underscanning (output)) - { - MetaCrtc *crtc; - const MetaCrtcConfig *crtc_config; - const MetaCrtcModeInfo *crtc_mode_info; - uint64_t hborder, vborder; - - crtc = meta_output_get_assigned_crtc (output); - crtc_config = meta_crtc_get_config (crtc); - crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); - - hborder = MIN (128, (uint64_t) round (crtc_mode_info->width * 0.05)); - vborder = MIN (128, (uint64_t) round (crtc_mode_info->height * 0.05)); - - g_debug ("Setting underscan of connector %s to %" G_GUINT64_FORMAT " x %" G_GUINT64_FORMAT, - meta_kms_connector_get_name (output_kms->kms_connector), - hborder, vborder); - - meta_kms_update_set_underscanning (kms_update, - output_kms->kms_connector, - hborder, vborder); - } - else - { - g_debug ("Unsetting underscan of connector %s", - meta_kms_connector_get_name (output_kms->kms_connector)); - - meta_kms_update_unset_underscanning (kms_update, - output_kms->kms_connector); - } -} - -uint32_t -meta_output_kms_get_connector_id (MetaOutputKms *output_kms) -{ - return meta_kms_connector_get_id (output_kms->kms_connector); -} - -gboolean -meta_output_kms_can_clone (MetaOutputKms *output_kms, - MetaOutputKms *other_output_kms) -{ - return meta_kms_connector_can_clone (output_kms->kms_connector, - other_output_kms->kms_connector); -} - -static GBytes * -meta_output_kms_read_edid (MetaOutputNative *output_native) -{ - MetaOutputKms *output_kms = META_OUTPUT_KMS (output_native); - const MetaKmsConnectorState *connector_state; - GBytes *edid_data; - - connector_state = - meta_kms_connector_get_current_state (output_kms->kms_connector); - edid_data = connector_state->edid_data; - if (!edid_data) - return NULL; - - return g_bytes_new_from_bytes (edid_data, 0, g_bytes_get_size (edid_data)); -} - -static void -add_common_modes (MetaOutputInfo *output_info, - MetaGpuKms *gpu_kms) -{ - MetaCrtcMode *crtc_mode; - GPtrArray *array; - float refresh_rate; - unsigned i; - unsigned max_hdisplay = 0; - unsigned max_vdisplay = 0; - float max_refresh_rate = 0.0; - float max_bandwidth = 0.0; - MetaKmsDevice *kms_device; - MetaKmsModeFlag flag_filter; - GList *l; - - for (i = 0; i < output_info->n_modes; i++) - { - MetaCrtcMode *crtc_mode = output_info->modes[i]; - MetaCrtcModeKms *crtc_mode_kms = META_CRTC_MODE_KMS (crtc_mode); - MetaKmsMode *kms_mode = meta_crtc_mode_kms_get_kms_mode (crtc_mode_kms); - const drmModeModeInfo *drm_mode = meta_kms_mode_get_drm_mode (kms_mode); - float bandwidth; - - refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode); - bandwidth = refresh_rate * drm_mode->hdisplay * drm_mode->vdisplay; - max_hdisplay = MAX (max_hdisplay, drm_mode->hdisplay); - max_vdisplay = MAX (max_vdisplay, drm_mode->vdisplay); - max_refresh_rate = MAX (max_refresh_rate, refresh_rate); - max_bandwidth = MAX (max_bandwidth, bandwidth); - } - - max_refresh_rate = MAX (max_refresh_rate, 60.0); - max_refresh_rate *= (1 + SYNC_TOLERANCE); - - kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - - array = g_ptr_array_new (); - - if (max_hdisplay > max_vdisplay) - flag_filter = META_KMS_MODE_FLAG_FALLBACK_LANDSCAPE; - else - flag_filter = META_KMS_MODE_FLAG_FALLBACK_PORTRAIT; - - for (l = meta_kms_device_get_fallback_modes (kms_device); l; l = l->next) - { - MetaKmsMode *fallback_mode = l->data; - const drmModeModeInfo *drm_mode; - float bandwidth; - - if (!(meta_kms_mode_get_flags (fallback_mode) & flag_filter)) - continue; - - drm_mode = meta_kms_mode_get_drm_mode (fallback_mode); - refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode); - bandwidth = refresh_rate * drm_mode->hdisplay * drm_mode->vdisplay; - if (drm_mode->hdisplay > max_hdisplay || - drm_mode->vdisplay > max_vdisplay || - refresh_rate > max_refresh_rate || - bandwidth > max_bandwidth) - continue; - - crtc_mode = meta_gpu_kms_get_mode_from_kms_mode (gpu_kms, fallback_mode); - g_ptr_array_add (array, crtc_mode); - } - - output_info->modes = g_renew (MetaCrtcMode *, output_info->modes, - output_info->n_modes + array->len); - memcpy (output_info->modes + output_info->n_modes, array->pdata, - array->len * sizeof (MetaCrtcMode *)); - output_info->n_modes += array->len; - - g_ptr_array_free (array, TRUE); -} - -static int -compare_modes (const void *one, - const void *two) -{ - MetaCrtcMode *crtc_mode_one = *(MetaCrtcMode **) one; - MetaCrtcMode *crtc_mode_two = *(MetaCrtcMode **) two; - const MetaCrtcModeInfo *crtc_mode_info_one = - meta_crtc_mode_get_info (crtc_mode_one); - const MetaCrtcModeInfo *crtc_mode_info_two = - meta_crtc_mode_get_info (crtc_mode_two); - - if (crtc_mode_info_one->width != crtc_mode_info_two->width) - return crtc_mode_info_one->width > crtc_mode_info_two->width ? -1 : 1; - if (crtc_mode_info_one->height != crtc_mode_info_two->height) - return crtc_mode_info_one->height > crtc_mode_info_two->height ? -1 : 1; - if (crtc_mode_info_one->refresh_rate != crtc_mode_info_two->refresh_rate) - return (crtc_mode_info_one->refresh_rate > crtc_mode_info_two->refresh_rate - ? -1 : 1); - - return g_strcmp0 (meta_crtc_mode_get_name (crtc_mode_one), - meta_crtc_mode_get_name (crtc_mode_two)); -} - -static gboolean -init_output_modes (MetaOutputInfo *output_info, - MetaGpuKms *gpu_kms, - MetaKmsConnector *kms_connector, - GError **error) -{ - const MetaKmsConnectorState *connector_state; - GList *l; - int i; - - connector_state = meta_kms_connector_get_current_state (kms_connector); - - output_info->preferred_mode = NULL; - - output_info->n_modes = g_list_length (connector_state->modes); - output_info->modes = g_new0 (MetaCrtcMode *, output_info->n_modes); - for (l = connector_state->modes, i = 0; l; l = l->next, i++) - { - MetaKmsMode *kms_mode = l->data; - const drmModeModeInfo *drm_mode = meta_kms_mode_get_drm_mode (kms_mode); - MetaCrtcMode *crtc_mode; - - crtc_mode = meta_gpu_kms_get_mode_from_kms_mode (gpu_kms, kms_mode); - output_info->modes[i] = crtc_mode; - if (drm_mode->type & DRM_MODE_TYPE_PREFERRED) - output_info->preferred_mode = output_info->modes[i]; - } - - if (connector_state->has_scaling) - { - meta_topic (META_DEBUG_KMS, "Adding common modes to connector %u on %s", - meta_kms_connector_get_id (kms_connector), - meta_gpu_kms_get_file_path (gpu_kms)); - add_common_modes (output_info, gpu_kms); - } - - if (!output_info->modes) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No modes available"); - return FALSE; - } - - qsort (output_info->modes, output_info->n_modes, - sizeof (MetaCrtcMode *), compare_modes); - - if (!output_info->preferred_mode) - output_info->preferred_mode = output_info->modes[0]; - - return TRUE; -} - -static MetaConnectorType -meta_kms_connector_type_from_drm (uint32_t drm_connector_type) -{ - g_warn_if_fail (drm_connector_type < META_CONNECTOR_TYPE_META); - - return (MetaConnectorType) drm_connector_type; -} - -MetaOutputKms * -meta_output_kms_new (MetaGpuKms *gpu_kms, - MetaKmsConnector *kms_connector, - MetaOutput *old_output, - GError **error) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - uint32_t connector_id; - uint32_t gpu_id; - g_autoptr (MetaOutputInfo) output_info = NULL; - MetaOutput *output; - MetaOutputKms *output_kms; - uint32_t drm_connector_type; - const MetaKmsConnectorState *connector_state; - GArray *crtcs; - GList *l; - - gpu_id = meta_gpu_kms_get_id (gpu_kms); - connector_id = meta_kms_connector_get_id (kms_connector); - - output_info = meta_output_info_new (); - output_info->name = g_strdup (meta_kms_connector_get_name (kms_connector)); - - connector_state = meta_kms_connector_get_current_state (kms_connector); - - output_info->panel_orientation_transform = - connector_state->panel_orientation_transform; - if (meta_monitor_transform_is_rotated (output_info->panel_orientation_transform)) - { - output_info->width_mm = connector_state->height_mm; - output_info->height_mm = connector_state->width_mm; - } - else - { - output_info->width_mm = connector_state->width_mm; - output_info->height_mm = connector_state->height_mm; - } - - if (!init_output_modes (output_info, gpu_kms, kms_connector, error)) - return NULL; - - crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCrtc *)); - - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - uint32_t crtc_idx; - - crtc_idx = meta_kms_crtc_get_idx (kms_crtc); - if (connector_state->common_possible_crtcs & (1 << crtc_idx)) - g_array_append_val (crtcs, crtc_kms); - } - - output_info->n_possible_crtcs = crtcs->len; - output_info->possible_crtcs = (MetaCrtc **) g_array_free (crtcs, FALSE); - - output_info->suggested_x = connector_state->suggested_x; - output_info->suggested_y = connector_state->suggested_y; - output_info->hotplug_mode_update = connector_state->hotplug_mode_update; - output_info->supports_underscanning = - meta_kms_connector_is_underscanning_supported (kms_connector); - - meta_output_info_parse_edid (output_info, connector_state->edid_data); - - drm_connector_type = meta_kms_connector_get_connector_type (kms_connector); - output_info->connector_type = - meta_kms_connector_type_from_drm (drm_connector_type); - - output_info->tile_info = connector_state->tile_info; - - output = g_object_new (META_TYPE_OUTPUT_KMS, - "id", ((uint64_t) gpu_id << 32) | connector_id, - "gpu", gpu, - "info", output_info, - NULL); - output_kms = META_OUTPUT_KMS (output); - output_kms->kms_connector = kms_connector; - - if (connector_state->current_crtc_id) - { - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) - { - MetaCrtc *crtc = l->data; - - if (meta_crtc_get_id (crtc) == connector_state->current_crtc_id) - { - MetaOutputAssignment output_assignment; - - if (old_output) - { - output_assignment = (MetaOutputAssignment) { - .is_primary = meta_output_is_primary (old_output), - .is_presentation = meta_output_is_presentation (old_output), - }; - } - else - { - output_assignment = (MetaOutputAssignment) { - .is_primary = FALSE, - .is_presentation = FALSE, - }; - } - meta_output_assign_crtc (output, crtc, &output_assignment); - break; - } - } - } - else - { - meta_output_unassign_crtc (output); - } - - return output_kms; -} - -static void -meta_output_kms_init (MetaOutputKms *output_kms) -{ -} - -static void -meta_output_kms_class_init (MetaOutputKmsClass *klass) -{ - MetaOutputNativeClass *output_native_class = META_OUTPUT_NATIVE_CLASS (klass); - - output_native_class->read_edid = meta_output_kms_read_edid; -} diff --git a/src/backends/native/meta-output-kms.h b/src/backends/native/meta-output-kms.h deleted file mode 100644 index 52acc6032..000000000 --- a/src/backends/native/meta-output-kms.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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. - */ - -#ifndef META_OUTPUT_KMS_H -#define META_OUTPUT_KMS_H - -#include "backends/meta-output.h" -#include "backends/native/meta-gpu-kms.h" -#include "backends/native/meta-kms-types.h" -#include "backends/native/meta-output-native.h" - -#define META_TYPE_OUTPUT_KMS (meta_output_kms_get_type ()) -G_DECLARE_FINAL_TYPE (MetaOutputKms, meta_output_kms, - META, OUTPUT_KMS, - MetaOutputNative) - -void meta_output_kms_set_power_save_mode (MetaOutputKms *output_kms, - uint64_t dpms_state, - MetaKmsUpdate *kms_update); - -void meta_output_kms_set_underscan (MetaOutputKms *output_kms, - MetaKmsUpdate *kms_update); - -gboolean meta_output_kms_can_clone (MetaOutputKms *output_kms, - MetaOutputKms *other_output_kms); - -MetaKmsConnector * meta_output_kms_get_kms_connector (MetaOutputKms *output_kms); - -uint32_t meta_output_kms_get_connector_id (MetaOutputKms *output_kms); - -MetaOutputKms * meta_output_kms_new (MetaGpuKms *gpu_kms, - MetaKmsConnector *kms_connector, - MetaOutput *old_output, - GError **error); - -#endif /* META_OUTPUT_KMS_H */ diff --git a/src/backends/native/meta-output-native.c b/src/backends/native/meta-output-native.c deleted file mode 100644 index f21b2ebc6..000000000 --- a/src/backends/native/meta-output-native.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ - -#include "config.h" - -#include "backends/native/meta-output-native.h" - -G_DEFINE_ABSTRACT_TYPE (MetaOutputNative, meta_output_native, - META_TYPE_OUTPUT) - -GBytes * -meta_output_native_read_edid (MetaOutputNative *output_native) -{ - MetaOutputNativeClass *klass = META_OUTPUT_NATIVE_GET_CLASS (output_native); - - return klass->read_edid (output_native); -} - -static void -meta_output_native_init (MetaOutputNative *output_native) -{ -} - -static void -meta_output_native_class_init (MetaOutputNativeClass *klass) -{ -} diff --git a/src/backends/native/meta-output-native.h b/src/backends/native/meta-output-native.h deleted file mode 100644 index f0475ae3b..000000000 --- a/src/backends/native/meta-output-native.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ - -#ifndef META_OUTPUT_NATIVE_H -#define META_OUTPUT_NATIVE_H - -#include "backends/meta-output.h" - -#define META_TYPE_OUTPUT_NATIVE (meta_output_native_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaOutputNative, meta_output_native, - META, OUTPUT_NATIVE, - MetaOutput) - -struct _MetaOutputNativeClass -{ - MetaOutputClass parent_class; - - GBytes * (* read_edid) (MetaOutputNative *output_native); -}; - -GBytes * meta_output_native_read_edid (MetaOutputNative *output_native); - -#endif /* META_OUTPUT_NATIVE_H */ diff --git a/src/backends/native/meta-output-virtual.c b/src/backends/native/meta-output-virtual.c deleted file mode 100644 index 12efb3338..000000000 --- a/src/backends/native/meta-output-virtual.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#include "config.h" - -#include "backends/native/meta-output-virtual.h" - -#include "backends/native/meta-crtc-mode-virtual.h" -#include "backends/native/meta-crtc-virtual.h" -#include "backends/meta-virtual-monitor.h" - -struct _MetaOutputVirtual -{ - MetaOutputNative parent; -}; - -#define META_OUTPUT_VIRTUAL_ID_BIT (((uint64_t) 1) << 63) - -G_DEFINE_TYPE (MetaOutputVirtual, meta_output_virtual, META_TYPE_OUTPUT_NATIVE) - -MetaOutputVirtual * -meta_output_virtual_new (uint64_t id, - const MetaVirtualMonitorInfo *info, - MetaCrtcVirtual *crtc_virtual, - MetaCrtcModeVirtual *crtc_mode_virtual) -{ - g_autoptr (MetaOutputInfo) output_info = NULL; - - output_info = meta_output_info_new (); - output_info->name = g_strdup_printf ("Meta-%" G_GUINT64_FORMAT, id); - - output_info->n_possible_crtcs = 1; - output_info->possible_crtcs = g_new0 (MetaCrtc *, 1); - output_info->possible_crtcs[0] = META_CRTC (crtc_virtual); - - output_info->hotplug_mode_update = FALSE; - output_info->suggested_x = -1; - output_info->suggested_y = -1; - - output_info->connector_type = META_CONNECTOR_TYPE_META; - output_info->vendor = g_strdup (info->vendor); - output_info->product = g_strdup (info->product); - output_info->serial = g_strdup (info->serial); - - output_info->n_modes = 1; - output_info->modes = g_new0 (MetaCrtcMode *, 1); - output_info->modes[0] = META_CRTC_MODE (crtc_mode_virtual); - output_info->preferred_mode = output_info->modes[0]; - - return g_object_new (META_TYPE_OUTPUT_VIRTUAL, - "id", META_OUTPUT_VIRTUAL_ID_BIT | id, - "info", output_info, - NULL); -} - -static void -meta_output_virtual_init (MetaOutputVirtual *output_virtual) -{ -} - -static void -meta_output_virtual_class_init (MetaOutputVirtualClass *klass) -{ -} diff --git a/src/backends/native/meta-output-virtual.h b/src/backends/native/meta-output-virtual.h deleted file mode 100644 index b04579f0d..000000000 --- a/src/backends/native/meta-output-virtual.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#ifndef META_OUTPUT_VIRTUAL_H -#define META_OUTPUT_VIRTUAL_H - -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-output-native.h" - -#define META_TYPE_OUTPUT_VIRTUAL (meta_output_virtual_get_type ()) -G_DECLARE_FINAL_TYPE (MetaOutputVirtual, meta_output_virtual, - META, OUTPUT_VIRTUAL, - MetaOutputNative) - -MetaOutputVirtual * meta_output_virtual_new (uint64_t id, - const MetaVirtualMonitorInfo *info, - MetaCrtcVirtual *crtc_virtual, - MetaCrtcModeVirtual *crtc_mode_virtual); - -#endif /* META_OUTPUT_VIRTUAL_H */ diff --git a/src/backends/native/meta-pointer-constraint-native.c b/src/backends/native/meta-pointer-constraint-native.c deleted file mode 100644 index 6a1c066ad..000000000 --- a/src/backends/native/meta-pointer-constraint-native.c +++ /dev/null @@ -1,694 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2020 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: - * Jonas Ådahl <jadahl@gmail.com> - */ - -#include "config.h" - -#include <glib-object.h> -#include <wayland-server.h> - -#include "core/meta-border.h" -#include "meta-pointer-constraint-native.h" - -struct _MetaPointerConstraintImplNative -{ - MetaPointerConstraintImpl parent; - MetaPointerConstraint *constraint; - cairo_region_t *region; -}; - -G_DEFINE_TYPE (MetaPointerConstraintImplNative, - meta_pointer_constraint_impl_native, - META_TYPE_POINTER_CONSTRAINT_IMPL); - -typedef struct _MetaBox -{ - int x1; - int y1; - int x2; - int y2; -} MetaBox; - -static MetaBorder * -add_border (GArray *borders, - float x1, - float y1, - float x2, - float y2, - MetaBorderMotionDirection blocking_directions) -{ - MetaBorder border; - - border = (MetaBorder) { - .line = (MetaLine2) { - .a = (MetaVector2) { - .x = x1, - .y = y1, - }, - .b = (MetaVector2) { - .x = x2, - .y = y2, - }, - }, - .blocking_directions = blocking_directions, - }; - - g_array_append_val (borders, border); - - return &g_array_index (borders, MetaBorder, borders->len - 1); -} - -static gint -compare_lines_x (gconstpointer a, - gconstpointer b) -{ - const MetaBorder *border_a = a; - const MetaBorder *border_b = b; - - if (border_a->line.a.x == border_b->line.a.x) - return border_a->line.b.x < border_b->line.b.x; - else - return border_a->line.a.x > border_b->line.a.x; -} - -static void -add_non_overlapping_edges (MetaBox *boxes, - unsigned int band_above_start, - unsigned int band_below_start, - unsigned int band_below_end, - GArray *borders) -{ - unsigned int i; - GArray *band_merge; - MetaBorder *border; - MetaBorder *prev_border; - MetaBorder *new_border; - - band_merge = g_array_new (FALSE, FALSE, sizeof *border); - - /* Add bottom band of previous row, and top band of current row, and - * sort them so lower left x coordinate comes first. If there are two - * borders with the same left x coordinate, the wider one comes first. - */ - for (i = band_above_start; i < band_below_start; i++) - { - MetaBox *box = &boxes[i]; - add_border (band_merge, box->x1, box->y2, box->x2, box->y2, - META_BORDER_MOTION_DIRECTION_POSITIVE_Y); - } - for (i = band_below_start; i < band_below_end; i++) - { - MetaBox *box= &boxes[i]; - add_border (band_merge, box->x1, box->y1, box->x2, box->y1, - META_BORDER_MOTION_DIRECTION_NEGATIVE_Y); - } - g_array_sort (band_merge, compare_lines_x); - - /* Combine the two combined bands so that any overlapping border is - * eliminated. */ - prev_border = NULL; - for (i = 0; i < band_merge->len; i++) - { - border = &g_array_index (band_merge, MetaBorder, i); - - g_assert (border->line.a.y == border->line.b.y); - g_assert (!prev_border || - prev_border->line.a.y == border->line.a.y); - g_assert (!prev_border || - (prev_border->line.a.x != border->line.a.x || - prev_border->line.b.x != border->line.b.x)); - g_assert (!prev_border || - prev_border->line.a.x <= border->line.a.x); - - if (prev_border && - prev_border->line.a.x == border->line.a.x) - { - /* - * ------------ + - * ------- = - * [ ]----- - */ - prev_border->line.a.x = border->line.b.x; - } - else if (prev_border && - prev_border->line.b.x == border->line.b.x) - { - /* - * ------------ + - * ------ = - * ------[ ] - */ - prev_border->line.b.x = border->line.a.x; - } - else if (prev_border && - prev_border->line.b.x == border->line.a.x) - { - /* - * -------- + - * ------ = - * -------------- - */ - prev_border->line.b.x = border->line.b.x; - } - else if (prev_border && - prev_border->line.b.x >= border->line.a.x) - { - /* - * --------------- + - * ------ = - * -----[ ]---- - */ - new_border = add_border (borders, - border->line.b.x, - border->line.b.y, - prev_border->line.b.x, - prev_border->line.b.y, - prev_border->blocking_directions); - prev_border->line.b.x = border->line.a.x; - prev_border = new_border; - } - else - { - g_assert (!prev_border || - prev_border->line.b.x < border->line.a.x); - /* - * First border or non-overlapping. - * - * ----- + - * ----- = - * ----- ----- - */ - g_array_append_val (borders, *border); - prev_border = &g_array_index (borders, MetaBorder, borders->len - 1); - } - } - - g_array_free (band_merge, FALSE); -} - -static void -add_band_bottom_edges (MetaBox *boxes, - int band_start, - int band_end, - GArray *borders) -{ - int i; - - for (i = band_start; i < band_end; i++) - { - add_border (borders, - boxes[i].x1, boxes[i].y2, - boxes[i].x2, boxes[i].y2, - META_BORDER_MOTION_DIRECTION_POSITIVE_Y); - } -} - -static void -region_to_outline (cairo_region_t *region, - GArray *borders) -{ - MetaBox *boxes; - int num_boxes; - int i; - int top_most, bottom_most; - int current_roof; - int prev_top; - int band_start, prev_band_start; - - /* - * Remove any overlapping lines from the set of rectangles. Note that - * pixman regions are grouped as rows of rectangles, where rectangles - * in one row never touch or overlap and are all of the same height. - * - * -------- --- -------- --- - * | | | | | | | | - * ----------====---- --- ----------- ----- --- - * | | => | | - * ----==========--------- ----- ---------- - * | | | | - * ------------------- ------------------- - * - */ - - num_boxes = cairo_region_num_rectangles (region); - boxes = g_new (MetaBox, num_boxes); - for (i = 0; i < num_boxes; i++) - { - cairo_rectangle_int_t rect; - cairo_region_get_rectangle (region, i, &rect); - boxes[i] = (MetaBox) { - .x1 = rect.x, - .y1 = rect.y, - .x2 = rect.x + rect.width, - .y2 = rect.y + rect.height, - }; - } - prev_top = 0; - top_most = boxes[0].y1; - current_roof = top_most; - bottom_most = boxes[num_boxes - 1].y2; - band_start = 0; - prev_band_start = 0; - for (i = 0; i < num_boxes; i++) - { - /* Detect if there is a vertical empty space, and add the lower - * level of the previous band if so was the case. */ - if (i > 0 && - boxes[i].y1 != prev_top && - boxes[i].y1 != boxes[i - 1].y2) - { - current_roof = boxes[i].y1; - add_band_bottom_edges (boxes, - band_start, - i, - borders); - } - - /* Special case adding the last band, since it won't be handled - * by the band change detection below. */ - if (boxes[i].y1 != current_roof && i == num_boxes - 1) - { - if (boxes[i].y1 != prev_top) - { - /* The last band is a single box, so we don't - * have a prev_band_start to tell us when the - * previous band started. */ - add_non_overlapping_edges (boxes, - band_start, - i, - i + 1, - borders); - } - else - { - add_non_overlapping_edges (boxes, - prev_band_start, - band_start, - i + 1, - borders); - } - } - - /* Detect when passing a band and combine the top border of the - * just passed band with the bottom band of the previous band. - */ - if (boxes[i].y1 != top_most && boxes[i].y1 != prev_top) - { - /* Combine the two passed bands. */ - if (prev_top != current_roof) - { - add_non_overlapping_edges (boxes, - prev_band_start, - band_start, - i, - borders); - } - - prev_band_start = band_start; - band_start = i; - } - - /* Add the top border if the box is part of the current roof. */ - if (boxes[i].y1 == current_roof) - { - add_border (borders, - boxes[i].x1, boxes[i].y1, - boxes[i].x2, boxes[i].y1, - META_BORDER_MOTION_DIRECTION_NEGATIVE_Y); - } - - /* Add the bottom border of the last band. */ - if (boxes[i].y2 == bottom_most) - { - add_border (borders, - boxes[i].x1, boxes[i].y2, - boxes[i].x2, boxes[i].y2, - META_BORDER_MOTION_DIRECTION_POSITIVE_Y); - } - - /* Always add the left border. */ - add_border (borders, - boxes[i].x1, boxes[i].y1, - boxes[i].x1, boxes[i].y2, - META_BORDER_MOTION_DIRECTION_NEGATIVE_X); - - /* Always add the right border. */ - add_border (borders, - boxes[i].x2, boxes[i].y1, - boxes[i].x2, boxes[i].y2, - META_BORDER_MOTION_DIRECTION_POSITIVE_X); - - prev_top = boxes[i].y1; - } - - g_free (boxes); -} - -static MetaBorder * -get_closest_border (GArray *borders, - MetaLine2 *motion, - uint32_t directions) -{ - MetaBorder *border; - MetaVector2 intersection; - MetaVector2 delta; - float distance_2; - MetaBorder *closest_border = NULL; - float closest_distance_2 = DBL_MAX; - unsigned int i; - - for (i = 0; i < borders->len; i++) - { - border = &g_array_index (borders, MetaBorder, i); - - if (!meta_border_is_blocking_directions (border, directions)) - continue; - - if (!meta_line2_intersects_with (&border->line, motion, &intersection)) - continue; - - delta = meta_vector2_subtract (intersection, motion->a); - distance_2 = delta.x*delta.x + delta.y*delta.y; - if (distance_2 < closest_distance_2) - { - closest_border = border; - closest_distance_2 = distance_2; - } - } - - return closest_border; -} - -static void -clamp_to_border (MetaBorder *border, - MetaLine2 *motion, - uint32_t *motion_dir) -{ - /* - * When clamping either rightward or downward motions, the motion needs to be - * clamped so that the destination coordinate does not end up on the border - * (see weston_pointer_clamp_event_to_region). Do this by clamping such - * motions to the border minus the smallest possible wl_fixed_t value. - * - * When clamping in either leftward or upward motion, the resulting coordinate - * needs to be clamped so that it is enough on the inside to avoid the - * inaccuracies of clutter's stage to actor transformation algorithm (the one - * used in clutter_actor_transform_stage_point) to make it end up outside the - * next motion. It also needs to be clamped so that to the wl_fixed_t - * coordinate may still be right on the border (i.e. at .0). Testing shows - * that the smallest wl_fixed_t value divided by 10 is small enough to make - * the wl_fixed_t coordinate .0 and large enough to avoid the inaccuracies of - * clutters transform algorithm. - */ - if (meta_border_is_horizontal (border)) - { - if (*motion_dir & META_BORDER_MOTION_DIRECTION_POSITIVE_Y) - motion->b.y = border->line.a.y - wl_fixed_to_double (1); - else - motion->b.y = border->line.a.y + wl_fixed_to_double (1) / 10; - *motion_dir &= ~(META_BORDER_MOTION_DIRECTION_POSITIVE_Y | - META_BORDER_MOTION_DIRECTION_NEGATIVE_Y); - } - else - { - if (*motion_dir & META_BORDER_MOTION_DIRECTION_POSITIVE_X) - motion->b.x = border->line.a.x - wl_fixed_to_double (1); - else - motion->b.x = border->line.a.x + wl_fixed_to_double (1) / 10; - *motion_dir &= ~(META_BORDER_MOTION_DIRECTION_POSITIVE_X | - META_BORDER_MOTION_DIRECTION_NEGATIVE_X); - } -} - -static uint32_t -get_motion_directions (MetaLine2 *motion) -{ - uint32_t directions = 0; - - if (motion->a.x < motion->b.x) - directions |= META_BORDER_MOTION_DIRECTION_POSITIVE_X; - else if (motion->a.x > motion->b.x) - directions |= META_BORDER_MOTION_DIRECTION_NEGATIVE_X; - if (motion->a.y < motion->b.y) - directions |= META_BORDER_MOTION_DIRECTION_POSITIVE_Y; - else if (motion->a.y > motion->b.y) - directions |= META_BORDER_MOTION_DIRECTION_NEGATIVE_Y; - - return directions; -} - -static void -meta_pointer_constraint_impl_native_constraint (MetaPointerConstraintImpl *constraint_impl, - ClutterInputDevice *device, - uint32_t time, - float prev_x, - float prev_y, - float *x_inout, - float *y_inout) -{ - MetaPointerConstraintImplNative *constraint_impl_native; - cairo_region_t *region; - float x, y; - GArray *borders; - MetaLine2 motion; - MetaBorder *closest_border; - uint32_t directions; - - constraint_impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (constraint_impl); - - region = cairo_region_reference (constraint_impl_native->region); - x = *x_inout; - y = *y_inout; - - /* For motions in a positive direction on any axis, append the smallest - * possible value representable in a Wayland absolute coordinate. This is - * in order to avoid not clamping motion that as a floating point number - * won't be clamped, but will be rounded up to be outside of the range - * of wl_fixed_t. */ - if (x > prev_x) - x += (float) wl_fixed_to_double(1); - if (y > prev_y) - y += (float) wl_fixed_to_double(1); - - borders = g_array_new (FALSE, FALSE, sizeof (MetaBorder)); - - /* - * Generate borders given the confine region we are to use. The borders - * are defined to be the outer region of the allowed area. This means - * top/left borders are "within" the allowed area, while bottom/right - * borders are outside. This needs to be considered when clamping - * confined motion vectors. - */ - region_to_outline (region, borders); - cairo_region_destroy (region); - - motion = (MetaLine2) { - .a = (MetaVector2) { - .x = prev_x, - .y = prev_y, - }, - .b = (MetaVector2) { - .x = x, - .y = y, - }, - }; - directions = get_motion_directions (&motion); - - while (directions) - { - closest_border = get_closest_border (borders, - &motion, - directions); - if (closest_border) - clamp_to_border (closest_border, &motion, &directions); - else - break; - } - - *x_inout = motion.b.x; - *y_inout = motion.b.y; - g_array_free (borders, FALSE); -} - -static float -point_to_border_distance_2 (MetaBorder *border, - float x, - float y) -{ - float orig_x, orig_y; - float dx, dy; - - if (meta_border_is_horizontal (border)) - { - if (x < border->line.a.x) - orig_x = border->line.a.x; - else if (x > border->line.b.x) - orig_x = border->line.b.x; - else - orig_x = x; - orig_y = border->line.a.y; - } - else - { - if (y < border->line.a.y) - orig_y = border->line.a.y; - else if (y > border->line.b.y) - orig_y = border->line.b.y; - else - orig_y = y; - orig_x = border->line.a.x; - } - - dx = fabsf (orig_x - x); - dy = fabsf (orig_y - y); - return dx*dx + dy*dy; -} - -static void -closest_point_behind_border (MetaBorder *border, - float *sx, - float *sy) -{ - switch (border->blocking_directions) - { - case META_BORDER_MOTION_DIRECTION_POSITIVE_X: - case META_BORDER_MOTION_DIRECTION_NEGATIVE_X: - if (border->blocking_directions == META_BORDER_MOTION_DIRECTION_POSITIVE_X) - *sx = border->line.a.x - wl_fixed_to_double (1); - else - *sx = border->line.a.x + wl_fixed_to_double (1); - if (*sy < border->line.a.y) - *sy = border->line.a.y + wl_fixed_to_double (1); - else if (*sy > border->line.b.y) - *sy = border->line.b.y - wl_fixed_to_double (1); - break; - case META_BORDER_MOTION_DIRECTION_POSITIVE_Y: - case META_BORDER_MOTION_DIRECTION_NEGATIVE_Y: - if (border->blocking_directions == META_BORDER_MOTION_DIRECTION_POSITIVE_Y) - *sy = border->line.a.y - wl_fixed_to_double (1); - else - *sy = border->line.a.y + wl_fixed_to_double (1); - if (*sx < border->line.a.x) - *sx = border->line.a.x + wl_fixed_to_double (1); - else if (*sx > (border->line.b.x)) - *sx = border->line.b.x - wl_fixed_to_double (1); - break; - } -} - -static void -meta_pointer_constraint_impl_native_ensure_constrained (MetaPointerConstraintImpl *constraint_impl, - ClutterInputDevice *device) -{ - MetaPointerConstraintImplNative *constraint_impl_native; - graphene_point_t point; - cairo_region_t *region; - float x; - float y; - - constraint_impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (constraint_impl); - region = cairo_region_reference (constraint_impl_native->region); - - clutter_seat_query_state (clutter_input_device_get_seat (device), - device, NULL, &point, NULL); - x = point.x; - y = point.y; - - if (!cairo_region_contains_point (region, (int) x, (int) y)) - { - GArray *borders; - float closest_distance_2 = FLT_MAX; - MetaBorder *closest_border = NULL; - ClutterSeat *seat; - unsigned int i; - - borders = g_array_new (FALSE, FALSE, sizeof (MetaBorder)); - - region_to_outline (region, borders); - - for (i = 0; i < borders->len; i++) - { - MetaBorder *border = &g_array_index (borders, MetaBorder, i); - float distance_2; - - distance_2 = point_to_border_distance_2 (border, x, y); - if (distance_2 < closest_distance_2) - { - closest_border = border; - closest_distance_2 = distance_2; - } - } - - closest_point_behind_border (closest_border, &x, &y); - - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - clutter_seat_warp_pointer (seat, x, y); - } - - cairo_region_destroy (region); -} - -static void -meta_pointer_constraint_impl_native_finalize (GObject *object) -{ - MetaPointerConstraintImplNative *constraint_impl_native; - - constraint_impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (object); - g_clear_pointer (&constraint_impl_native->region, cairo_region_destroy); - - G_OBJECT_CLASS (meta_pointer_constraint_impl_native_parent_class)->finalize (object); -} - -static void -meta_pointer_constraint_impl_native_init (MetaPointerConstraintImplNative *constraint_impl_native) -{ -} - -static void -meta_pointer_constraint_impl_native_class_init (MetaPointerConstraintImplNativeClass *klass) -{ - MetaPointerConstraintImplClass *constraint_impl_class; - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_pointer_constraint_impl_native_finalize; - - constraint_impl_class = META_POINTER_CONSTRAINT_IMPL_CLASS (klass); - constraint_impl_class->constrain = meta_pointer_constraint_impl_native_constraint; - constraint_impl_class->ensure_constrained = - meta_pointer_constraint_impl_native_ensure_constrained; -} - - -MetaPointerConstraintImpl * -meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint, - const cairo_region_t *region) -{ - MetaPointerConstraintImplNative *constraint_impl; - - constraint_impl = g_object_new (META_TYPE_POINTER_CONSTRAINT_IMPL_NATIVE, - NULL); - constraint_impl->constraint = constraint; - constraint_impl->region = cairo_region_copy (region); - - return META_POINTER_CONSTRAINT_IMPL (constraint_impl); -} diff --git a/src/backends/native/meta-pointer-constraint-native.h b/src/backends/native/meta-pointer-constraint-native.h deleted file mode 100644 index 83a2e575d..000000000 --- a/src/backends/native/meta-pointer-constraint-native.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2020 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: - * Carlos Garnacho <carlosg@gnome.org> - */ - -#ifndef META_POINTER_CONSTRAINT_NATIVE_H -#define META_POINTER_CONSTRAINT_NATIVE_H - -#include <glib-object.h> - -#include "clutter/clutter.h" -#include "backends/meta-pointer-constraint.h" - -G_BEGIN_DECLS - -#define META_TYPE_POINTER_CONSTRAINT_IMPL_NATIVE (meta_pointer_constraint_impl_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaPointerConstraintImplNative, - meta_pointer_constraint_impl_native, - META, POINTER_CONSTRAINT_IMPL_NATIVE, - MetaPointerConstraintImpl) - -MetaPointerConstraintImpl * meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint_impl, - const cairo_region_t *region); - -G_END_DECLS - -#endif /* META_POINTER_CONSTRAINT_NATIVE_H */ diff --git a/src/backends/native/meta-renderer-native-gles3.c b/src/backends/native/meta-renderer-native-gles3.c deleted file mode 100644 index c0eb77554..000000000 --- a/src/backends/native/meta-renderer-native-gles3.c +++ /dev/null @@ -1,160 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. - * - * 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. - * - */ - -#include "config.h" - -#define GL_GLEXT_PROTOTYPES - -#include "backends/native/meta-renderer-native-gles3.h" - -#include <GLES3/gl3.h> -#include <drm_fourcc.h> -#include <errno.h> -#include <gio/gio.h> -#include <string.h> - -#include "backends/meta-egl-ext.h" -#include "backends/meta-gles3.h" -#include "backends/meta-gles3-table.h" - -/* - * GL/gl.h being included may conflict with gl3.h on some architectures. - * Make sure that hasn't happened on any architecture. - */ -#ifdef GL_VERSION_1_1 -#error "Somehow included OpenGL headers when we shouldn't have" -#endif - -static void -paint_egl_image (MetaGles3 *gles3, - EGLImageKHR egl_image, - int width, - int height) -{ - GLuint texture; - GLuint framebuffer; - - meta_gles3_clear_error (gles3); - - GLBAS (gles3, glGenFramebuffers, (1, &framebuffer)); - GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); - - GLBAS (gles3, glActiveTexture, (GL_TEXTURE0)); - GLBAS (gles3, glGenTextures, (1, &texture)); - GLBAS (gles3, glBindTexture, (GL_TEXTURE_2D, texture)); - GLEXT (gles3, glEGLImageTargetTexture2DOES, (GL_TEXTURE_2D, egl_image)); - GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST)); - GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST)); - GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE)); - GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE)); - GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_WRAP_R_OES, - GL_CLAMP_TO_EDGE)); - - GLBAS (gles3, glFramebufferTexture2D, (GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, texture, 0)); - - GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); - GLBAS (gles3, glBlitFramebuffer, (0, height, width, 0, - 0, 0, width, height, - GL_COLOR_BUFFER_BIT, - GL_NEAREST)); - - GLBAS (gles3, glDeleteTextures, (1, &texture)); - GLBAS (gles3, glDeleteFramebuffers, (1, &framebuffer)); -} - -gboolean -meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - MetaGles3 *gles3, - EGLDisplay egl_display, - EGLContext egl_context, - EGLSurface egl_surface, - struct gbm_bo *shared_bo, - GError **error) -{ - int shared_bo_fd; - unsigned int width; - unsigned int height; - uint32_t i, n_planes; - uint32_t strides[4] = { 0 }; - uint32_t offsets[4] = { 0 }; - uint64_t modifiers[4] = { 0 }; - int fds[4] = { -1, -1, -1, -1 }; - uint32_t format; - EGLImageKHR egl_image; - gboolean use_modifiers; - - shared_bo_fd = gbm_bo_get_fd (shared_bo); - if (shared_bo_fd < 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to export gbm_bo: %s", strerror (errno)); - return FALSE; - } - - width = gbm_bo_get_width (shared_bo); - height = gbm_bo_get_height (shared_bo); - format = gbm_bo_get_format (shared_bo); - - n_planes = gbm_bo_get_plane_count (shared_bo); - for (i = 0; i < n_planes; i++) - { - strides[i] = gbm_bo_get_stride_for_plane (shared_bo, i); - offsets[i] = gbm_bo_get_offset (shared_bo, i); - modifiers[i] = gbm_bo_get_modifier (shared_bo); - fds[i] = shared_bo_fd; - } - - /* Workaround for https://gitlab.gnome.org/GNOME/mutter/issues/18 */ - if (modifiers[0] == DRM_FORMAT_MOD_LINEAR || - modifiers[0] == DRM_FORMAT_MOD_INVALID) - use_modifiers = FALSE; - else - use_modifiers = TRUE; - - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - width, - height, - format, - n_planes, - fds, - strides, - offsets, - use_modifiers ? modifiers : NULL, - error); - close (shared_bo_fd); - - if (!egl_image) - return FALSE; - - paint_egl_image (gles3, egl_image, width, height); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - return TRUE; -} diff --git a/src/backends/native/meta-renderer-native-gles3.h b/src/backends/native/meta-renderer-native-gles3.h deleted file mode 100644 index 4e7324c8d..000000000 --- a/src/backends/native/meta-renderer-native-gles3.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. - * - * 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. - * - */ - -#ifndef META_RENDERER_NATIVE_GLES3_H -#define META_RENDERER_NATIVE_GLES3_H - -#include <gbm.h> - -#include "backends/meta-egl.h" -#include "backends/meta-gles3.h" - -gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - MetaGles3 *gles3, - EGLDisplay egl_display, - EGLContext egl_context, - EGLSurface egl_surface, - struct gbm_bo *shared_bo, - GError **error); - -#endif /* META_RENDERER_NATIVE_GLES3_H */ diff --git a/src/backends/native/meta-renderer-native-private.h b/src/backends/native/meta-renderer-native-private.h deleted file mode 100644 index acadb3fff..000000000 --- a/src/backends/native/meta-renderer-native-private.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016-2020 Red Hat - * Copyright (c) 2018,2019 DisplayLink (UK) Ltd. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef META_RENDERER_NATIVE_PRIVATE_H -#define META_RENDERER_NATIVE_PRIVATE_H - -#include "backends/meta-gles3.h" -#include "backends/native/meta-renderer-native.h" - -typedef enum _MetaSharedFramebufferCopyMode -{ - /* Zero-copy: primary GPU exports, secondary GPU imports as KMS FB */ - META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO, - /* the secondary GPU will make the copy */ - META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU, - /* - * The copy is made in the primary GPU rendering context, either - * as a CPU copy through Cogl read-pixels or as primary GPU copy - * using glBlitFramebuffer. - */ - META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY -} MetaSharedFramebufferCopyMode; - -typedef struct _MetaRendererNativeGpuData -{ - MetaRendererNative *renderer_native; - - MetaDeviceFile *device_file; - - struct { - struct gbm_device *device; - } gbm; - -#ifdef HAVE_EGL_DEVICE - struct { - EGLDeviceEXT device; - } egl; -#endif - - MetaRendererNativeMode mode; - - EGLDisplay egl_display; - - /* - * Fields used for blitting iGPU framebuffer content onto dGPU framebuffers. - */ - struct { - MetaSharedFramebufferCopyMode copy_mode; - gboolean is_hardware_rendering; - gboolean has_EGL_EXT_image_dma_buf_import_modifiers; - - /* For GPU blit mode */ - EGLContext egl_context; - EGLConfig egl_config; - } secondary; -} MetaRendererNativeGpuData; - -MetaEgl * meta_renderer_native_get_egl (MetaRendererNative *renderer_native); - -MetaGles3 * meta_renderer_native_get_gles3 (MetaRendererNative *renderer_native); - -MetaRendererNativeGpuData * meta_renderer_native_get_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms); - -gboolean meta_renderer_native_has_pending_mode_sets (MetaRendererNative *renderer_native); - -gboolean meta_renderer_native_has_pending_mode_set (MetaRendererNative *renderer_native); - -void meta_renderer_native_notify_mode_sets_reset (MetaRendererNative *renderer_native); - -void meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native); - -void meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen); - -CoglFramebuffer * meta_renderer_native_create_dma_buf_framebuffer (MetaRendererNative *renderer_native, - int dmabuf_fd, - uint32_t width, - uint32_t height, - uint32_t stride, - uint32_t offset, - uint64_t modifier, - uint32_t drm_format, - GError **error); - -gboolean meta_renderer_native_pop_pending_mode_set (MetaRendererNative *renderer_native, - MetaRendererView *view); - -const CoglWinsysVtable * meta_get_renderer_native_parent_vtable (void); - -#endif /* META_RENDERER_NATIVE_PRIVATE_H */ diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c deleted file mode 100644 index eb6771b80..000000000 --- a/src/backends/native/meta-renderer-native.c +++ /dev/null @@ -1,2264 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016 Red Hat - * Copyright (c) 2018,2019 DisplayLink (UK) Ltd. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - * Rob Bradford <rob@linux.intel.com> (from cogl-winsys-egl-kms.c) - * Kristian Høgsberg (from eglkms.c) - * Benjamin Franzke (from eglkms.c) - * Robert Bragg <robert@linux.intel.com> (from cogl-winsys-egl-kms.c) - * Neil Roberts <neil@linux.intel.com> (from cogl-winsys-egl-kms.c) - * Jonas Ådahl <jadahl@redhat.com> - * - */ - -#include "config.h" - -#include <drm_fourcc.h> -#include <errno.h> -#include <gbm.h> -#include <gio/gio.h> -#include <glib-object.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "backends/meta-gles3.h" -#include "backends/meta-logical-monitor.h" -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-cogl-utils.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-crtc-virtual.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-onscreen-native.h" -#include "backends/native/meta-renderer-native-private.h" -#include "cogl/cogl.h" -#include "core/boxes-private.h" - -#ifndef EGL_DRM_MASTER_FD_EXT -#define EGL_DRM_MASTER_FD_EXT 0x333C -#endif - -/* added in libdrm 2.4.95 */ -#ifndef DRM_FORMAT_INVALID -#define DRM_FORMAT_INVALID 0 -#endif - -struct _MetaRendererNative -{ - MetaRenderer parent; - - MetaGpuKms *primary_gpu_kms; - - MetaGles3 *gles3; - - gboolean use_modifiers; - - GHashTable *gpu_datas; - - GList *pending_mode_set_views; - gboolean pending_mode_set; - - GList *kept_alive_onscreens; - - GList *power_save_page_flip_onscreens; - guint power_save_page_flip_source_id; -}; - -static void -initable_iface_init (GInitableIface *initable_iface); - -G_DEFINE_TYPE_WITH_CODE (MetaRendererNative, - meta_renderer_native, - META_TYPE_RENDERER, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable; -static const CoglWinsysVtable *parent_vtable; - -static gboolean -meta_renderer_native_ensure_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms, - GError **error); - -static void -meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native); - -const CoglWinsysVtable * -meta_get_renderer_native_parent_vtable (void) -{ - return parent_vtable; -} - -static void -meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data) -{ - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - - if (renderer_gpu_data->secondary.egl_context != EGL_NO_CONTEXT) - { - meta_egl_destroy_context (egl, - renderer_gpu_data->egl_display, - renderer_gpu_data->secondary.egl_context, - NULL); - } - - if (renderer_gpu_data->egl_display != EGL_NO_DISPLAY) - meta_egl_terminate (egl, renderer_gpu_data->egl_display, NULL); - - g_clear_pointer (&renderer_gpu_data->gbm.device, gbm_device_destroy); - g_clear_pointer (&renderer_gpu_data->device_file, meta_device_file_release); - g_free (renderer_gpu_data); -} - -MetaRendererNativeGpuData * -meta_renderer_native_get_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms) -{ - return g_hash_table_lookup (renderer_native->gpu_datas, gpu_kms); -} - -static MetaRendererNative * -meta_renderer_native_from_gpu (MetaGpuKms *gpu_kms) -{ - MetaBackend *backend = meta_gpu_get_backend (META_GPU (gpu_kms)); - - return META_RENDERER_NATIVE (meta_backend_get_renderer (backend)); -} - -struct gbm_device * -meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms) -{ - MetaRendererNative *renderer_native = meta_renderer_native_from_gpu (gpu_kms); - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - gpu_kms); - - return renderer_gpu_data->gbm.device; -} - -MetaGpuKms * -meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_native) -{ - return renderer_native->primary_gpu_kms; -} - -MetaDeviceFile * -meta_renderer_native_get_primary_device_file (MetaRendererNative *renderer_native) -{ - MetaGpuKms *gpu_kms = renderer_native->primary_gpu_kms; - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - gpu_kms); - return renderer_gpu_data->device_file; -} - -static MetaRendererNativeGpuData * -meta_create_renderer_native_gpu_data (void) -{ - return g_new0 (MetaRendererNativeGpuData, 1); -} - -MetaEgl * -meta_renderer_native_get_egl (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - - return meta_backend_get_egl (meta_renderer_get_backend (renderer)); -} - -gboolean -meta_renderer_native_use_modifiers (MetaRendererNative *renderer_native) -{ - return renderer_native->use_modifiers; -} - -MetaGles3 * -meta_renderer_native_get_gles3 (MetaRendererNative *renderer_native) -{ - return renderer_native->gles3; -} - -gboolean -meta_renderer_native_has_pending_mode_sets (MetaRendererNative *renderer_native) -{ - return !!renderer_native->pending_mode_set_views; -} - -gboolean -meta_renderer_native_has_pending_mode_set (MetaRendererNative *renderer_native) -{ - return renderer_native->pending_mode_set; -} - -static void -meta_renderer_native_disconnect (CoglRenderer *cogl_renderer) -{ - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - - g_free (cogl_renderer_egl); -} - -static gboolean -meta_renderer_native_connect (CoglRenderer *cogl_renderer, - GError **error) -{ - CoglRendererEGL *cogl_renderer_egl; - MetaRendererNative *renderer_native = cogl_renderer->custom_winsys_user_data; - MetaGpuKms *gpu_kms; - MetaRendererNativeGpuData *renderer_gpu_data; - - cogl_renderer->winsys = g_new0 (CoglRendererEGL, 1); - cogl_renderer_egl = cogl_renderer->winsys; - - gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native); - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - gpu_kms); - - cogl_renderer_egl->platform_vtable = &_cogl_winsys_egl_vtable; - cogl_renderer_egl->platform = renderer_gpu_data; - cogl_renderer_egl->edpy = renderer_gpu_data->egl_display; - - if (!_cogl_winsys_egl_renderer_connect_common (cogl_renderer, error)) - goto fail; - - return TRUE; - -fail: - meta_renderer_native_disconnect (cogl_renderer); - - return FALSE; -} - -static int -meta_renderer_native_add_egl_config_attributes (CoglDisplay *cogl_display, - const CoglFramebufferConfig *config, - EGLint *attributes) -{ - CoglRendererEGL *cogl_renderer_egl = cogl_display->renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - int i = 0; - - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - attributes[i++] = EGL_SURFACE_TYPE; - attributes[i++] = EGL_WINDOW_BIT; - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - attributes[i++] = EGL_SURFACE_TYPE; - attributes[i++] = EGL_PBUFFER_BIT; - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - attributes[i++] = EGL_SURFACE_TYPE; - attributes[i++] = EGL_STREAM_BIT_KHR; - break; -#endif - } - - return i; -} - -static gboolean -choose_egl_config_from_gbm_format (MetaEgl *egl, - EGLDisplay egl_display, - const EGLint *attributes, - uint32_t gbm_format, - EGLConfig *out_config, - GError **error) -{ - EGLConfig *egl_configs; - EGLint n_configs; - EGLint i; - - egl_configs = meta_egl_choose_all_configs (egl, egl_display, - attributes, - &n_configs, - error); - if (!egl_configs) - return FALSE; - - for (i = 0; i < n_configs; i++) - { - EGLint visual_id; - - if (!meta_egl_get_config_attrib (egl, egl_display, - egl_configs[i], - EGL_NATIVE_VISUAL_ID, - &visual_id, - error)) - { - g_free (egl_configs); - return FALSE; - } - - if ((uint32_t) visual_id == gbm_format) - { - *out_config = egl_configs[i]; - g_free (egl_configs); - return TRUE; - } - } - - g_free (egl_configs); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No EGL config matching supported GBM format found"); - return FALSE; -} - -static gboolean -meta_renderer_native_choose_egl_config (CoglDisplay *cogl_display, - EGLint *attributes, - EGLConfig *out_config, - GError **error) -{ - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - EGLDisplay egl_display = cogl_renderer_egl->edpy; - - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - return choose_egl_config_from_gbm_format (egl, - egl_display, - attributes, - GBM_FORMAT_XRGB8888, - out_config, - error); - case META_RENDERER_NATIVE_MODE_SURFACELESS: - *out_config = EGL_NO_CONFIG_KHR; - return TRUE; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - return meta_egl_choose_first_config (egl, - egl_display, - attributes, - out_config, - error); -#endif - } - - return FALSE; -} - -static gboolean -meta_renderer_native_setup_egl_display (CoglDisplay *cogl_display, - GError **error) -{ - CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; - CoglRendererEGL *cogl_renderer_egl = cogl_display->renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - - cogl_display_egl->platform = renderer_native; - - /* Force a full modeset / drmModeSetCrtc on - * the first swap buffers call. - */ - meta_renderer_native_queue_modes_reset (renderer_native); - - return TRUE; -} - -static void -meta_renderer_native_destroy_egl_display (CoglDisplay *cogl_display) -{ -} - -static EGLSurface -create_dummy_pbuffer_surface (EGLDisplay egl_display, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - EGLConfig pbuffer_config; - static const EGLint pbuffer_config_attribs[] = { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_ALPHA_SIZE, 0, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE - }; - static const EGLint pbuffer_attribs[] = { - EGL_WIDTH, 16, - EGL_HEIGHT, 16, - EGL_NONE - }; - - if (!meta_egl_choose_first_config (egl, egl_display, pbuffer_config_attribs, - &pbuffer_config, error)) - return EGL_NO_SURFACE; - - return meta_egl_create_pbuffer_surface (egl, egl_display, - pbuffer_config, pbuffer_attribs, - error); -} - -static gboolean -meta_renderer_native_egl_context_created (CoglDisplay *cogl_display, - GError **error) -{ - CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - - if ((cogl_renderer_egl->private_features & - COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT) == 0) - { - cogl_display_egl->dummy_surface = - create_dummy_pbuffer_surface (cogl_renderer_egl->edpy, error); - if (cogl_display_egl->dummy_surface == EGL_NO_SURFACE) - return FALSE; - } - - if (!_cogl_winsys_egl_make_current (cogl_display, - cogl_display_egl->dummy_surface, - cogl_display_egl->dummy_surface, - cogl_display_egl->egl_context)) - { - g_set_error (error, COGL_WINSYS_ERROR, - COGL_WINSYS_ERROR_CREATE_CONTEXT, - "Failed to make context current"); - return FALSE; - } - - return TRUE; -} - -static void -meta_renderer_native_egl_cleanup_context (CoglDisplay *cogl_display) -{ - CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - - if (cogl_display_egl->dummy_surface != EGL_NO_SURFACE) - { - meta_egl_destroy_surface (egl, - cogl_renderer_egl->edpy, - cogl_display_egl->dummy_surface, - NULL); - cogl_display_egl->dummy_surface = EGL_NO_SURFACE; - } -} - -static CoglContext * -cogl_context_from_renderer_native (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - - return clutter_backend_get_cogl_context (clutter_backend); -} - -CoglFramebuffer * -meta_renderer_native_create_dma_buf_framebuffer (MetaRendererNative *renderer_native, - int dmabuf_fd, - uint32_t width, - uint32_t height, - uint32_t stride, - uint32_t offset, - uint64_t modifier, - uint32_t drm_format, - GError **error) -{ - CoglContext *cogl_context = - cogl_context_from_renderer_native (renderer_native); - CoglDisplay *cogl_display = cogl_context->display; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - EGLDisplay egl_display = cogl_renderer_egl->edpy; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - EGLImageKHR egl_image; - uint32_t strides[1]; - uint32_t offsets[1]; - uint64_t modifiers[1]; - CoglPixelFormat cogl_format; - CoglEglImageFlags flags; - CoglTexture2D *cogl_tex; - CoglOffscreen *cogl_fbo; - int ret; - - ret = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); - g_assert (ret); - - strides[0] = stride; - offsets[0] = offset; - modifiers[0] = modifier; - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - width, - height, - drm_format, - 1 /* n_planes */, - &dmabuf_fd, - strides, - offsets, - modifiers, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - return NULL; - - flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; - cogl_tex = cogl_egl_texture_2d_new_from_image (cogl_context, - width, - height, - cogl_format, - egl_image, - flags, - error); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - if (!cogl_tex) - return NULL; - - cogl_fbo = cogl_offscreen_new_with_texture (COGL_TEXTURE (cogl_tex)); - cogl_object_unref (cogl_tex); - - if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (cogl_fbo), error)) - { - g_object_unref (cogl_fbo); - return NULL; - } - - return COGL_FRAMEBUFFER (cogl_fbo); -} - -static void -configure_disabled_crtcs (MetaKmsDevice *kms_device) -{ - MetaKms *kms = meta_kms_device_get_kms (kms_device); - GList *l; - - for (l = meta_kms_device_get_crtcs (kms_device); l; l = l->next) - { - MetaKmsCrtc *kms_crtc = l->data; - MetaCrtcKms *crtc_kms = meta_crtc_kms_from_kms_crtc (kms_crtc); - MetaKmsUpdate *kms_update; - - if (meta_crtc_get_config (META_CRTC (crtc_kms))) - continue; - - if (!meta_kms_crtc_is_active (kms_crtc)) - continue; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_kms_update_mode_set (kms_update, kms_crtc, NULL, NULL); - } -} - -static gboolean -dummy_power_save_page_flip_cb (gpointer user_data) -{ - MetaRendererNative *renderer_native = user_data; - - g_list_foreach (renderer_native->power_save_page_flip_onscreens, - (GFunc) meta_onscreen_native_dummy_power_save_page_flip, - NULL); - g_clear_list (&renderer_native->power_save_page_flip_onscreens, - g_object_unref); - renderer_native->power_save_page_flip_source_id = 0; - - return G_SOURCE_REMOVE; -} - -void -meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen) -{ - const unsigned int timeout_ms = 100; - - if (!renderer_native->power_save_page_flip_source_id) - { - renderer_native->power_save_page_flip_source_id = - g_timeout_add (timeout_ms, - dummy_power_save_page_flip_cb, - renderer_native); - } - - renderer_native->power_save_page_flip_onscreens = - g_list_prepend (renderer_native->power_save_page_flip_onscreens, - g_object_ref (onscreen)); -} - -static void -clear_kept_alive_onscreens (MetaRendererNative *renderer_native) -{ - g_clear_list (&renderer_native->kept_alive_onscreens, - g_object_unref); -} - -static gboolean -is_gpu_unused (gpointer key, - gpointer value, - gpointer user_data) -{ - GHashTable *used_gpus = user_data; - - return !g_hash_table_contains (used_gpus, key); -} - -static void -free_unused_gpu_datas (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - g_autoptr (GHashTable) used_gpus = NULL; - GList *l; - - used_gpus = g_hash_table_new (NULL, NULL); - g_hash_table_add (used_gpus, renderer_native->primary_gpu_kms); - - for (l = meta_renderer_get_views (renderer); l; l = l->next) - { - MetaRendererView *view = l->data; - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); - MetaGpu *gpu; - - gpu = meta_crtc_get_gpu (crtc); - if (!gpu) - continue; - - g_hash_table_add (used_gpus, gpu); - } - - g_hash_table_foreach_remove (renderer_native->gpu_datas, - is_gpu_unused, - used_gpus); -} - -void -meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaKms *kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend)); - GList *l; - - for (l = meta_kms_get_devices (kms); l; l = l->next) - { - MetaKmsDevice *kms_device = l->data; - MetaKmsUpdate *kms_update; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *feedback_error; - - configure_disabled_crtcs (kms_device); - - kms_update = meta_kms_get_pending_update (kms, kms_device); - if (!kms_update) - continue; - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags); - - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - break; - case META_KMS_FEEDBACK_FAILED: - feedback_error = meta_kms_feedback_get_error (kms_feedback); - if (!g_error_matches (feedback_error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", feedback_error->message); - break; - } - } - - clear_kept_alive_onscreens (renderer_native); - - meta_kms_notify_modes_set (kms); - - free_unused_gpu_datas (renderer_native); -} - -static void -unset_disabled_crtcs (MetaBackend *backend, - MetaKms *kms) -{ - GList *l; - - meta_topic (META_DEBUG_KMS, "Disabling all disabled CRTCs"); - - for (l = meta_backend_get_gpus (backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - MetaKmsDevice *kms_device = - meta_gpu_kms_get_kms_device (META_GPU_KMS (gpu)); - GList *k; - gboolean did_mode_set = FALSE; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - - for (k = meta_gpu_get_crtcs (gpu); k; k = k->next) - { - MetaCrtc *crtc = k->data; - MetaKmsUpdate *kms_update; - - if (meta_crtc_get_config (crtc)) - continue; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_crtc_kms_set_mode (META_CRTC_KMS (crtc), kms_update); - - did_mode_set = TRUE; - } - - if (!did_mode_set) - continue; - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, - kms_device, - flags); - if (meta_kms_feedback_get_result (kms_feedback) != - META_KMS_FEEDBACK_PASSED) - { - const GError *error = meta_kms_feedback_get_error (kms_feedback); - - if (!g_error_matches (error, G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", error->message); - } - } -} - -static CoglDmaBufHandle * -meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer, - int width, - int height, - GError **error) -{ - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - { - CoglFramebuffer *dmabuf_fb; - CoglDmaBufHandle *dmabuf_handle; - struct gbm_bo *new_bo; - int stride; - int offset; - int bpp; - int dmabuf_fd = -1; - - new_bo = gbm_bo_create (renderer_gpu_data->gbm.device, - width, height, DRM_FORMAT_XRGB8888, - GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR); - - if (!new_bo) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to allocate buffer"); - return NULL; - } - - dmabuf_fd = gbm_bo_get_fd (new_bo); - - if (dmabuf_fd == -1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS, - "Failed to export buffer's DMA fd: %s", - g_strerror (errno)); - return NULL; - } - - stride = gbm_bo_get_stride (new_bo); - offset = gbm_bo_get_offset (new_bo, 0); - bpp = 4; - dmabuf_fb = - meta_renderer_native_create_dma_buf_framebuffer (renderer_native, - dmabuf_fd, - width, height, - stride, - offset, - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_XRGB8888, - error); - - if (!dmabuf_fb) - return NULL; - - dmabuf_handle = - cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd, - width, height, stride, offset, bpp, - new_bo, - (GDestroyNotify) gbm_bo_destroy); - g_object_unref (dmabuf_fb); - return dmabuf_handle; - } - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: -#endif - break; - } - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, - "Current mode does not support exporting DMA buffers"); - - return NULL; -} - -static gboolean -meta_renderer_native_init_egl_context (CoglContext *cogl_context, - GError **error) -{ -#ifdef HAVE_EGL_DEVICE - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; -#endif - - COGL_FLAGS_SET (cogl_context->winsys_features, - COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT, - TRUE); - COGL_FLAGS_SET (cogl_context->winsys_features, - COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT, - TRUE); - COGL_FLAGS_SET (cogl_context->winsys_features, - COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN, - TRUE); - -#ifdef HAVE_EGL_DEVICE - if (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_EGL_DEVICE) - COGL_FLAGS_SET (cogl_context->features, - COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL, TRUE); -#endif - - return TRUE; -} - -static const CoglWinsysEGLVtable -_cogl_winsys_egl_vtable = { - .add_config_attributes = meta_renderer_native_add_egl_config_attributes, - .choose_config = meta_renderer_native_choose_egl_config, - .display_setup = meta_renderer_native_setup_egl_display, - .display_destroy = meta_renderer_native_destroy_egl_display, - .context_created = meta_renderer_native_egl_context_created, - .cleanup_context = meta_renderer_native_egl_cleanup_context, - .context_init = meta_renderer_native_init_egl_context -}; - -static void -meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - GList *l; - - g_clear_list (&renderer_native->pending_mode_set_views, NULL); - for (l = meta_renderer_get_views (renderer); l; l = l->next) - { - ClutterStageView *stage_view = l->data; - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (stage_view); - - if (COGL_IS_ONSCREEN (framebuffer)) - { - renderer_native->pending_mode_set_views = - g_list_prepend (renderer_native->pending_mode_set_views, - stage_view); - } - } - renderer_native->pending_mode_set = TRUE; - - meta_topic (META_DEBUG_KMS, "Queue mode set"); -} - -void -meta_renderer_native_notify_mode_sets_reset (MetaRendererNative *renderer_native) -{ - renderer_native->pending_mode_set = FALSE; -} - -gboolean -meta_renderer_native_pop_pending_mode_set (MetaRendererNative *renderer_native, - MetaRendererView *view) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaPowerSave power_save_mode; - GList *link; - - g_assert (META_IS_RENDERER_VIEW (view)); - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode != META_POWER_SAVE_ON) - return FALSE; - - link = g_list_find (renderer_native->pending_mode_set_views, view); - if (!link) - return FALSE; - - renderer_native->pending_mode_set_views = - g_list_delete_link (renderer_native->pending_mode_set_views, link); - return TRUE; -} - -static CoglOffscreen * -meta_renderer_native_create_offscreen (MetaRendererNative *renderer, - CoglContext *context, - gint view_width, - gint view_height, - GError **error) -{ - CoglOffscreen *fb; - CoglTexture2D *tex; - - tex = cogl_texture_2d_new_with_size (context, view_width, view_height); - cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (tex), FALSE); - - if (!cogl_texture_allocate (COGL_TEXTURE (tex), error)) - { - cogl_object_unref (tex); - return FALSE; - } - - fb = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex)); - cogl_object_unref (tex); - if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (fb), error)) - { - g_object_unref (fb); - return FALSE; - } - - return fb; -} - -static const CoglWinsysVtable * -get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer) -{ - static gboolean vtable_inited = FALSE; - static CoglWinsysVtable vtable; - - if (!vtable_inited) - { - /* The this winsys is a subclass of the EGL winsys so we - start by copying its vtable */ - - parent_vtable = _cogl_winsys_egl_get_vtable (); - vtable = *parent_vtable; - - vtable.id = COGL_WINSYS_ID_CUSTOM; - vtable.name = "EGL_KMS"; - - vtable.renderer_connect = meta_renderer_native_connect; - vtable.renderer_disconnect = meta_renderer_native_disconnect; - vtable.renderer_create_dma_buf = meta_renderer_native_create_dma_buf; - - vtable_inited = TRUE; - } - - return &vtable; -} - -static CoglRenderer * -meta_renderer_native_create_cogl_renderer (MetaRenderer *renderer) -{ - CoglRenderer *cogl_renderer; - - cogl_renderer = cogl_renderer_new (); - cogl_renderer_set_custom_winsys (cogl_renderer, - get_native_cogl_winsys_vtable, - renderer); - return cogl_renderer; -} - -static MetaMonitorTransform -calculate_view_transform (MetaMonitorManager *monitor_manager, - MetaLogicalMonitor *logical_monitor, - MetaOutput *output, - MetaCrtc *crtc) -{ - MetaMonitorTransform crtc_transform; - - crtc = meta_output_get_assigned_crtc (output); - crtc_transform = - meta_output_logical_to_crtc_transform (output, logical_monitor->transform); - - if (meta_monitor_manager_is_transform_handled (monitor_manager, - crtc, - crtc_transform)) - return META_MONITOR_TRANSFORM_NORMAL; - else - return crtc_transform; -} - -static gboolean -should_force_shadow_fb (MetaRendererNative *renderer_native, - MetaGpuKms *primary_gpu) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - CoglContext *cogl_context = - cogl_context_from_renderer_native (renderer_native); - MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (primary_gpu); - - if (meta_renderer_is_hardware_accelerated (renderer)) - return FALSE; - - if (!cogl_has_feature (cogl_context, COGL_FEATURE_ID_BLIT_FRAMEBUFFER)) - return FALSE; - - return meta_kms_device_prefers_shadow_buffer (kms_device); -} - -static CoglFramebuffer * -create_fallback_offscreen (MetaRendererNative *renderer_native, - CoglContext *cogl_context, - int width, - int height) -{ - CoglOffscreen *fallback_offscreen; - GError *error = NULL; - - fallback_offscreen = meta_renderer_native_create_offscreen (renderer_native, - cogl_context, - width, - height, - &error); - if (!fallback_offscreen) - { - g_error ("Failed to create fallback offscreen framebuffer: %s", - error->message); - } - - return COGL_FRAMEBUFFER (fallback_offscreen); -} - -static MetaRendererView * -meta_renderer_native_create_view (MetaRenderer *renderer, - MetaLogicalMonitor *logical_monitor, - MetaOutput *output, - MetaCrtc *crtc) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - CoglContext *cogl_context = - cogl_context_from_renderer_native (renderer_native); - CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); - const MetaCrtcConfig *crtc_config; - const MetaCrtcModeInfo *crtc_mode_info; - MetaMonitorTransform view_transform; - g_autoptr (CoglFramebuffer) framebuffer = NULL; - g_autoptr (CoglOffscreen) offscreen = NULL; - gboolean use_shadowfb; - float scale; - int onscreen_width; - int onscreen_height; - MetaRectangle view_layout; - MetaRendererView *view; - EGLSurface egl_surface; - GError *error = NULL; - - crtc_config = meta_crtc_get_config (crtc); - crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); - onscreen_width = crtc_mode_info->width; - onscreen_height = crtc_mode_info->height; - - if (META_IS_CRTC_KMS (crtc)) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - MetaOnscreenNative *onscreen_native; - - if (!meta_renderer_native_ensure_gpu_data (renderer_native, - gpu_kms, - &error)) - { - g_warning ("Failed to create secondary GPU data for %s: %s", - meta_gpu_kms_get_file_path (gpu_kms), - error->message); - use_shadowfb = FALSE; - framebuffer = create_fallback_offscreen (renderer_native, - cogl_context, - onscreen_width, - onscreen_height); - } - else - { - MetaGpuKms *primary_gpu_kms = renderer_native->primary_gpu_kms; - - onscreen_native = meta_onscreen_native_new (renderer_native, - primary_gpu_kms, - output, - crtc, - cogl_context, - onscreen_width, - onscreen_height); - - if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen_native), &error)) - { - g_warning ("Failed to allocate onscreen framebuffer for %s: %s", - meta_gpu_kms_get_file_path (gpu_kms), - error->message); - use_shadowfb = FALSE; - framebuffer = create_fallback_offscreen (renderer_native, - cogl_context, - onscreen_width, - onscreen_height); - } - else - { - use_shadowfb = should_force_shadow_fb (renderer_native, - primary_gpu_kms); - framebuffer = COGL_FRAMEBUFFER (onscreen_native); - } - } - } - else - { - CoglOffscreen *virtual_onscreen; - - g_assert (META_IS_CRTC_VIRTUAL (crtc)); - - virtual_onscreen = meta_renderer_native_create_offscreen (renderer_native, - cogl_context, - onscreen_width, - onscreen_height, - &error); - if (!virtual_onscreen) - g_error ("Failed to allocate back buffer texture: %s", error->message); - use_shadowfb = FALSE; - framebuffer = COGL_FRAMEBUFFER (virtual_onscreen); - } - - view_transform = calculate_view_transform (monitor_manager, - logical_monitor, - output, - crtc); - if (view_transform != META_MONITOR_TRANSFORM_NORMAL) - { - int offscreen_width; - int offscreen_height; - - if (meta_monitor_transform_is_rotated (view_transform)) - { - offscreen_width = onscreen_height; - offscreen_height = onscreen_width; - } - else - { - offscreen_width = onscreen_width; - offscreen_height = onscreen_height; - } - - offscreen = meta_renderer_native_create_offscreen (renderer_native, - cogl_context, - offscreen_width, - offscreen_height, - &error); - if (!offscreen) - g_error ("Failed to allocate back buffer texture: %s", error->message); - } - - if (meta_is_stage_views_scaled ()) - scale = meta_logical_monitor_get_scale (logical_monitor); - else - scale = 1.0; - - meta_rectangle_from_graphene_rect (&crtc_config->layout, - META_ROUNDING_STRATEGY_ROUND, - &view_layout); - view = g_object_new (META_TYPE_RENDERER_VIEW, - "name", meta_output_get_name (output), - "stage", meta_backend_get_stage (backend), - "layout", &view_layout, - "crtc", crtc, - "scale", scale, - "framebuffer", framebuffer, - "offscreen", offscreen, - "use-shadowfb", use_shadowfb, - "transform", view_transform, - "refresh-rate", crtc_mode_info->refresh_rate, - "vblank-duration-us", crtc_mode_info->vblank_duration_us, - NULL); - - if (META_IS_ONSCREEN_NATIVE (framebuffer)) - { - CoglDisplayEGL *cogl_display_egl; - CoglOnscreenEgl *onscreen_egl; - - meta_onscreen_native_set_view (COGL_ONSCREEN (framebuffer), view); - - /* Ensure we don't point to stale surfaces when creating the offscreen */ - cogl_display_egl = cogl_display->winsys; - onscreen_egl = COGL_ONSCREEN_EGL (framebuffer); - egl_surface = cogl_onscreen_egl_get_egl_surface (onscreen_egl); - _cogl_winsys_egl_make_current (cogl_display, - egl_surface, - egl_surface, - cogl_display_egl->egl_context); - } - - return view; -} - -static void -keep_current_onscreens_alive (MetaRenderer *renderer) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - GList *views; - GList *l; - - views = meta_renderer_get_views (renderer); - for (l = views; l; l = l->next) - { - ClutterStageView *stage_view = l->data; - CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (stage_view); - - renderer_native->kept_alive_onscreens = - g_list_prepend (renderer_native->kept_alive_onscreens, - g_object_ref (onscreen)); - } -} - -static void -meta_renderer_native_rebuild_views (MetaRenderer *renderer) -{ - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - MetaRendererClass *parent_renderer_class = - META_RENDERER_CLASS (meta_renderer_native_parent_class); - - meta_kms_discard_pending_page_flips (kms); - - keep_current_onscreens_alive (renderer); - - parent_renderer_class->rebuild_views (renderer); - - meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer)); -} - -void -meta_renderer_native_prepare_frame (MetaRendererNative *renderer_native, - MetaRendererView *view, - ClutterFrame *frame) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); - MetaPowerSave power_save_mode; - MetaCrtcKms *crtc_kms; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - - if (!META_IS_CRTC_KMS (crtc)) - return; - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode != META_POWER_SAVE_ON) - return; - - crtc_kms = META_CRTC_KMS (crtc); - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); - kms_device = meta_kms_crtc_get_device (kms_crtc); - - meta_crtc_kms_maybe_set_gamma (crtc_kms, kms_device); -} - -void -meta_renderer_native_finish_frame (MetaRendererNative *renderer_native, - MetaRendererView *view, - ClutterFrame *frame) -{ - if (!clutter_frame_has_result (frame)) - { - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); - - if (COGL_IS_ONSCREEN (framebuffer)) - { - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - - meta_onscreen_native_finish_frame (onscreen, frame); - } - } -} - -static gboolean -create_secondary_egl_config (MetaEgl *egl, - MetaRendererNativeMode mode, - EGLDisplay egl_display, - EGLConfig *egl_config, - GError **error) -{ - EGLint attributes[] = { - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_ALPHA_SIZE, EGL_DONT_CARE, - EGL_BUFFER_SIZE, EGL_DONT_CARE, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_NONE - }; - - switch (mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - case META_RENDERER_NATIVE_MODE_SURFACELESS: - return choose_egl_config_from_gbm_format (egl, - egl_display, - attributes, - GBM_FORMAT_XRGB8888, - egl_config, - error); -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - return meta_egl_choose_first_config (egl, - egl_display, - attributes, - egl_config, - error); -#endif - } - - return FALSE; -} - -static EGLContext -create_secondary_egl_context (MetaEgl *egl, - EGLDisplay egl_display, - EGLConfig egl_config, - GError **error) -{ - EGLint attributes[] = { - EGL_CONTEXT_CLIENT_VERSION, 3, - EGL_NONE - }; - - return meta_egl_create_context (egl, - egl_display, - egl_config, - EGL_NO_CONTEXT, - attributes, - error); -} - -static void -meta_renderer_native_ensure_gles3 (MetaRendererNative *renderer_native) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - - if (renderer_native->gles3) - return; - - renderer_native->gles3 = meta_gles3_new (egl); -} - -static void -maybe_restore_cogl_egl_api (MetaRendererNative *renderer_native) -{ - CoglContext *cogl_context; - CoglDisplay *cogl_display; - CoglRenderer *cogl_renderer; - - cogl_context = cogl_context_from_renderer_native (renderer_native); - if (!cogl_context) - return; - - cogl_display = cogl_context_get_display (cogl_context); - cogl_renderer = cogl_display_get_renderer (cogl_display); - cogl_renderer_bind_api (cogl_renderer); -} - -static gboolean -init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, - GError **error) -{ - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - EGLDisplay egl_display = renderer_gpu_data->egl_display; - EGLConfig egl_config; - EGLContext egl_context; - const char **missing_gl_extensions; - const char *renderer_str; - - meta_egl_bind_api (egl, EGL_OPENGL_ES_API, NULL); - - if (!create_secondary_egl_config (egl, renderer_gpu_data->mode, egl_display, - &egl_config, error)) - goto err; - - egl_context = create_secondary_egl_context (egl, egl_display, egl_config, error); - if (egl_context == EGL_NO_CONTEXT) - goto err; - - meta_renderer_native_ensure_gles3 (renderer_native); - - if (!meta_egl_make_current (egl, - egl_display, - EGL_NO_SURFACE, - EGL_NO_SURFACE, - egl_context, - error)) - { - meta_egl_destroy_context (egl, egl_display, egl_context, NULL); - goto err; - } - - renderer_str = (const char *) glGetString (GL_RENDERER); - if (g_str_has_prefix (renderer_str, "llvmpipe") || - g_str_has_prefix (renderer_str, "softpipe") || - g_str_has_prefix (renderer_str, "swrast")) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Do not want to use software renderer (%s), falling back to CPU copy path", - renderer_str); - goto err_fail_with_context; - } - - if (!meta_gles3_has_extensions (renderer_native->gles3, - &missing_gl_extensions, - "GL_OES_EGL_image_external", - NULL)) - { - char *missing_gl_extensions_str; - - missing_gl_extensions_str = g_strjoinv (", ", - (char **) missing_gl_extensions); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing OpenGL ES extensions: %s", - missing_gl_extensions_str); - g_free (missing_gl_extensions_str); - g_free (missing_gl_extensions); - - goto err_fail_with_context; - } - - renderer_gpu_data->secondary.is_hardware_rendering = TRUE; - renderer_gpu_data->secondary.egl_context = egl_context; - renderer_gpu_data->secondary.egl_config = egl_config; - renderer_gpu_data->secondary.copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU; - - renderer_gpu_data->secondary.has_EGL_EXT_image_dma_buf_import_modifiers = - meta_egl_has_extensions (egl, egl_display, NULL, - "EGL_EXT_image_dma_buf_import_modifiers", - NULL); - - maybe_restore_cogl_egl_api (renderer_native); - - return TRUE; - -err_fail_with_context: - meta_egl_make_current (egl, - egl_display, - EGL_NO_SURFACE, - EGL_NO_SURFACE, - EGL_NO_CONTEXT, - NULL); - meta_egl_destroy_context (egl, egl_display, egl_context, NULL); - -err: - maybe_restore_cogl_egl_api (renderer_native); - - return FALSE; -} - -static void -init_secondary_gpu_data_cpu (MetaRendererNativeGpuData *renderer_gpu_data) -{ - renderer_gpu_data->secondary.is_hardware_rendering = FALSE; - - /* First try ZERO, it automatically falls back to PRIMARY as needed */ - renderer_gpu_data->secondary.copy_mode = - META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO; -} - -static void -init_secondary_gpu_data (MetaRendererNativeGpuData *renderer_gpu_data) -{ - GError *error = NULL; - - if (init_secondary_gpu_data_gpu (renderer_gpu_data, &error)) - return; - - g_message ("Failed to initialize accelerated iGPU/dGPU framebuffer sharing: %s", - error->message); - g_error_free (error); - - init_secondary_gpu_data_cpu (renderer_gpu_data); -} - -static gboolean -gpu_kms_is_hardware_rendering (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms) -{ - MetaRendererNativeGpuData *data; - - data = meta_renderer_native_get_gpu_data (renderer_native, gpu_kms); - return data->secondary.is_hardware_rendering; -} - -static EGLDisplay -init_gbm_egl_display (MetaRendererNative *renderer_native, - struct gbm_device *gbm_device, - GError **error) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - EGLDisplay egl_display; - - if (!meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL, - "EGL_MESA_platform_gbm", - NULL) && - !meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL, - "EGL_KHR_platform_gbm", - NULL)) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Missing extension for GBM renderer: EGL_KHR_platform_gbm"); - return EGL_NO_DISPLAY; - } - - egl_display = meta_egl_get_platform_display (egl, - EGL_PLATFORM_GBM_KHR, - gbm_device, NULL, error); - if (egl_display == EGL_NO_DISPLAY) - return EGL_NO_DISPLAY; - - if (!meta_egl_initialize (egl, egl_display, error)) - return EGL_NO_DISPLAY; - - return egl_display; -} - -static MetaRendererNativeGpuData * -create_renderer_gpu_data_gbm (MetaRendererNative *renderer_native, - MetaDeviceFile *device_file, - GError **error) -{ - struct gbm_device *gbm_device; - MetaRendererNativeGpuData *renderer_gpu_data; - g_autoptr (GError) local_error = NULL; - - gbm_device = gbm_create_device (meta_device_file_get_fd (device_file)); - if (!gbm_device) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to create gbm device: %s", g_strerror (errno)); - return NULL; - } - - renderer_gpu_data = meta_create_renderer_native_gpu_data (); - renderer_gpu_data->device_file = meta_device_file_acquire (device_file); - renderer_gpu_data->renderer_native = renderer_native; - renderer_gpu_data->gbm.device = gbm_device; - renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_GBM; - - renderer_gpu_data->egl_display = init_gbm_egl_display (renderer_native, - gbm_device, - &local_error); - if (renderer_gpu_data->egl_display == EGL_NO_DISPLAY) - { - g_debug ("GBM EGL init for %s failed: %s", - meta_device_file_get_path (device_file), - local_error->message); - - init_secondary_gpu_data_cpu (renderer_gpu_data); - return renderer_gpu_data; - } - - init_secondary_gpu_data (renderer_gpu_data); - return renderer_gpu_data; -} - -static EGLDisplay -init_surfaceless_egl_display (MetaRendererNative *renderer_native, - GError **error) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - EGLDisplay egl_display; - - if (!meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL, - "EGL_MESA_platform_surfaceless", - NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing EGL platform required for surfaceless context: " - "EGL_MESA_platform_surfaceless"); - return EGL_NO_DISPLAY; - } - - egl_display = meta_egl_get_platform_display (egl, - EGL_PLATFORM_SURFACELESS_MESA, - EGL_DEFAULT_DISPLAY, - NULL, error); - if (egl_display == EGL_NO_DISPLAY) - return EGL_NO_DISPLAY; - - if (!meta_egl_initialize (egl, egl_display, error)) - return EGL_NO_DISPLAY; - - if (!meta_egl_has_extensions (egl, egl_display, NULL, - "EGL_KHR_no_config_context", - NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing EGL extension required for surfaceless context: " - "EGL_KHR_no_config_context"); - return EGL_NO_DISPLAY; - } - - return egl_display; -} - -static MetaRendererNativeGpuData * -create_renderer_gpu_data_surfaceless (MetaRendererNative *renderer_native, - GError **error) -{ - MetaRendererNativeGpuData *renderer_gpu_data; - EGLDisplay egl_display; - - egl_display = init_surfaceless_egl_display (renderer_native, error); - if (egl_display == EGL_NO_DISPLAY) - return NULL; - - renderer_gpu_data = meta_create_renderer_native_gpu_data (); - renderer_gpu_data->renderer_native = renderer_native; - renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_SURFACELESS; - renderer_gpu_data->egl_display = egl_display; - - return renderer_gpu_data; -} - -#ifdef HAVE_EGL_DEVICE -static const char * -get_drm_device_file (MetaEgl *egl, - EGLDeviceEXT device, - GError **error) -{ - if (!meta_egl_egl_device_has_extensions (egl, device, - NULL, - "EGL_EXT_device_drm", - NULL)) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Missing required EGLDevice extension EGL_EXT_device_drm"); - return NULL; - } - - return meta_egl_query_device_string (egl, device, - EGL_DRM_DEVICE_FILE_EXT, - error); -} - -static EGLDeviceEXT -find_egl_device (MetaRendererNative *renderer_native, - MetaDeviceFile *device_file, - GError **error) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - const char **missing_extensions; - EGLint num_devices; - EGLDeviceEXT *devices; - const char *kms_file_path; - EGLDeviceEXT device; - EGLint i; - - if (!meta_egl_has_extensions (egl, - EGL_NO_DISPLAY, - &missing_extensions, - "EGL_EXT_device_base", - NULL)) - { - char *missing_extensions_str; - - missing_extensions_str = g_strjoinv (", ", (char **) missing_extensions); - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Missing EGL extensions required for EGLDevice renderer: %s", - missing_extensions_str); - g_free (missing_extensions_str); - g_free (missing_extensions); - return EGL_NO_DEVICE_EXT; - } - - if (!meta_egl_query_devices (egl, 0, NULL, &num_devices, error)) - return EGL_NO_DEVICE_EXT; - - devices = g_new0 (EGLDeviceEXT, num_devices); - if (!meta_egl_query_devices (egl, num_devices, devices, &num_devices, - error)) - { - g_free (devices); - return EGL_NO_DEVICE_EXT; - } - - kms_file_path = meta_device_file_get_path (device_file); - - device = EGL_NO_DEVICE_EXT; - for (i = 0; i < num_devices; i++) - { - const char *egl_device_drm_path; - - g_clear_error (error); - - egl_device_drm_path = get_drm_device_file (egl, devices[i], error); - if (!egl_device_drm_path) - continue; - - if (g_str_equal (egl_device_drm_path, kms_file_path)) - { - device = devices[i]; - break; - } - } - g_free (devices); - - if (device == EGL_NO_DEVICE_EXT) - { - if (!*error) - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to find matching EGLDeviceEXT"); - return EGL_NO_DEVICE_EXT; - } - - return device; -} - -static EGLDisplay -get_egl_device_display (MetaRendererNative *renderer_native, - MetaDeviceFile *device_file, - EGLDeviceEXT egl_device, - GError **error) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - int kms_fd = meta_device_file_get_fd (device_file); - EGLint platform_attribs[] = { - EGL_DRM_MASTER_FD_EXT, kms_fd, - EGL_NONE - }; - - return meta_egl_get_platform_display (egl, EGL_PLATFORM_DEVICE_EXT, - (void *) egl_device, - platform_attribs, - error); -} - -static int -count_drm_devices (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - - return g_list_length (meta_backend_get_gpus (backend)); -} - -static MetaRendererNativeGpuData * -create_renderer_gpu_data_egl_device (MetaRendererNative *renderer_native, - MetaDeviceFile *device_file, - GError **error) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - const char **missing_extensions; - EGLDeviceEXT egl_device; - EGLDisplay egl_display; - MetaRendererNativeGpuData *renderer_gpu_data; - - if (count_drm_devices (renderer_native) != 1) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "EGLDevice currently only works with single GPU systems"); - return NULL; - } - - egl_device = find_egl_device (renderer_native, device_file, error); - if (egl_device == EGL_NO_DEVICE_EXT) - return NULL; - - egl_display = get_egl_device_display (renderer_native, device_file, - egl_device, error); - if (egl_display == EGL_NO_DISPLAY) - return NULL; - - if (!meta_egl_initialize (egl, egl_display, error)) - return NULL; - - if (!meta_egl_has_extensions (egl, - egl_display, - &missing_extensions, - "EGL_NV_output_drm_flip_event", - "EGL_EXT_output_base", - "EGL_EXT_output_drm", - "EGL_KHR_stream", - "EGL_KHR_stream_producer_eglsurface", - "EGL_EXT_stream_consumer_egloutput", - "EGL_EXT_stream_acquire_mode", - NULL)) - { - char *missing_extensions_str; - - missing_extensions_str = g_strjoinv (", ", (char **) missing_extensions); - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Missing EGL extensions required for EGLDevice renderer: %s", - missing_extensions_str); - meta_egl_terminate (egl, egl_display, NULL); - g_free (missing_extensions_str); - g_free (missing_extensions); - return NULL; - } - - renderer_gpu_data = meta_create_renderer_native_gpu_data (); - renderer_gpu_data->device_file = meta_device_file_acquire (device_file); - renderer_gpu_data->renderer_native = renderer_native; - renderer_gpu_data->egl.device = egl_device; - renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_EGL_DEVICE; - renderer_gpu_data->egl_display = egl_display; - - return renderer_gpu_data; -} -#endif /* HAVE_EGL_DEVICE */ - -static MetaRendererNativeGpuData * -meta_renderer_native_create_renderer_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms, - GError **error) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - MetaRendererNativeGpuData *renderer_gpu_data; - MetaDeviceFileFlags device_file_flags = META_DEVICE_FILE_FLAG_NONE; - g_autoptr (MetaDeviceFile) device_file = NULL; - GError *gbm_error = NULL; -#ifdef HAVE_EGL_DEVICE - GError *egl_device_error = NULL; -#endif - - if (!gpu_kms) - return create_renderer_gpu_data_surfaceless (renderer_native, error); - - if (!(meta_kms_device_get_flags (meta_gpu_kms_get_kms_device (gpu_kms)) & - META_KMS_DEVICE_FLAG_NO_MODE_SETTING)) - device_file_flags = META_DEVICE_FILE_FLAG_TAKE_CONTROL; - - device_file = meta_device_pool_open (device_pool, - meta_gpu_kms_get_file_path (gpu_kms), - device_file_flags, - error); - if (!device_file) - return NULL; - -#ifdef HAVE_EGL_DEVICE - /* Try to initialize the EGLDevice backend first. Whenever we use a - * non-NVIDIA GPU, the EGLDevice enumeration function won't find a match, and - * we'll fall back to GBM (which will always succeed as it has a software - * rendering fallback) - */ - renderer_gpu_data = create_renderer_gpu_data_egl_device (renderer_native, - device_file, - &egl_device_error); - if (renderer_gpu_data) - return renderer_gpu_data; -#endif - - renderer_gpu_data = create_renderer_gpu_data_gbm (renderer_native, - device_file, - &gbm_error); - if (renderer_gpu_data) - { -#ifdef HAVE_EGL_DEVICE - g_error_free (egl_device_error); -#endif - return renderer_gpu_data; - } - - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to initialize renderer: " - "%s" -#ifdef HAVE_EGL_DEVICE - ", %s" -#endif - , gbm_error->message -#ifdef HAVE_EGL_DEVICE - , egl_device_error->message -#endif - ); - - g_error_free (gbm_error); -#ifdef HAVE_EGL_DEVICE - g_error_free (egl_device_error); -#endif - - return NULL; -} - -static gboolean -create_renderer_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms, - GError **error) -{ - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = - meta_renderer_native_create_renderer_gpu_data (renderer_native, - gpu_kms, - error); - if (!renderer_gpu_data) - return FALSE; - - g_hash_table_insert (renderer_native->gpu_datas, - gpu_kms, - renderer_gpu_data); - - return TRUE; -} - -static gboolean -meta_renderer_native_ensure_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms, - GError **error) -{ - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = g_hash_table_lookup (renderer_native->gpu_datas, gpu_kms); - if (renderer_gpu_data) - return TRUE; - - return create_renderer_gpu_data (renderer_native, gpu_kms, error); -} - -static void -on_gpu_added (MetaBackendNative *backend_native, - MetaGpuKms *gpu_kms, - MetaRendererNative *renderer_native) -{ - MetaBackend *backend = META_BACKEND (backend_native); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); - GError *error = NULL; - - if (!create_renderer_gpu_data (renderer_native, gpu_kms, &error)) - { - g_warning ("on_gpu_added: could not create gpu_data for gpu %s: %s", - meta_gpu_kms_get_file_path (gpu_kms), error->message); - g_clear_error (&error); - } - - _cogl_winsys_egl_ensure_current (cogl_display); -} - -static void -on_power_save_mode_changed (MetaMonitorManager *monitor_manager, - MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - MetaPowerSave power_save_mode; - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode == META_POWER_SAVE_ON) - meta_renderer_native_queue_modes_reset (renderer_native); - else - meta_kms_discard_pending_page_flips (kms); -} - -void -meta_renderer_native_reset_modes (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - - unset_disabled_crtcs (backend, kms); -} - -static MetaGpuKms * -choose_primary_gpu_unchecked (MetaBackend *backend, - MetaRendererNative *renderer_native) -{ - GList *gpus = meta_backend_get_gpus (backend); - GList *l; - int allow_sw; - - /* - * Check first hardware rendering devices, and if none found, - * then software rendering devices. - */ - for (allow_sw = 0; allow_sw < 2; allow_sw++) - { - /* First check if one was explicitly configured. */ - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - - if (meta_kms_device_get_flags (kms_device) & - META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY) - { - g_message ("GPU %s selected primary given udev rule", - meta_gpu_kms_get_file_path (gpu_kms)); - return gpu_kms; - } - } - - /* Prefer a platform device */ - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - - if (meta_gpu_kms_is_platform_device (gpu_kms) && - (allow_sw == 1 || - gpu_kms_is_hardware_rendering (renderer_native, gpu_kms))) - { - g_message ("Integrated GPU %s selected as primary", - meta_gpu_kms_get_file_path (gpu_kms)); - return gpu_kms; - } - } - - /* Otherwise a device we booted with */ - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - - if (meta_gpu_kms_is_boot_vga (gpu_kms) && - (allow_sw == 1 || - gpu_kms_is_hardware_rendering (renderer_native, gpu_kms))) - { - g_message ("Boot VGA GPU %s selected as primary", - meta_gpu_kms_get_file_path (gpu_kms)); - return gpu_kms; - } - } - - /* Fall back to any device */ - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - - if (allow_sw == 1 || - gpu_kms_is_hardware_rendering (renderer_native, gpu_kms)) - { - g_message ("GPU %s selected as primary", - meta_gpu_kms_get_file_path (gpu_kms)); - return gpu_kms; - } - } - } - - g_assert_not_reached (); - return NULL; -} - -static MetaGpuKms * -choose_primary_gpu (MetaBackend *backend, - MetaRendererNative *renderer_native, - GError **error) -{ - MetaGpuKms *gpu_kms; - MetaRendererNativeGpuData *renderer_gpu_data; - - gpu_kms = choose_primary_gpu_unchecked (backend, renderer_native); - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - gpu_kms); - if (renderer_gpu_data->egl_display == EGL_NO_DISPLAY) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "The GPU %s chosen as primary is not supported by EGL.", - meta_gpu_kms_get_file_path (gpu_kms)); - return NULL; - } - - return gpu_kms; -} - -static gboolean -meta_renderer_native_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (initable); - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - GList *gpus; - GList *l; - - gpus = meta_backend_get_gpus (backend); - if (gpus) - { - const char *use_kms_modifiers_debug_env; - - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - - if (!create_renderer_gpu_data (renderer_native, gpu_kms, error)) - return FALSE; - } - - renderer_native->primary_gpu_kms = choose_primary_gpu (backend, - renderer_native, - error); - if (!renderer_native->primary_gpu_kms) - return FALSE; - - use_kms_modifiers_debug_env = g_getenv ("MUTTER_DEBUG_USE_KMS_MODIFIERS"); - if (use_kms_modifiers_debug_env) - { - renderer_native->use_modifiers = - g_strcmp0 (use_kms_modifiers_debug_env, "1") == 0; - } - else - { - renderer_native->use_modifiers = - !meta_gpu_kms_disable_modifiers (renderer_native->primary_gpu_kms); - } - - meta_topic (META_DEBUG_KMS, "Usage of KMS modifiers is %s", - renderer_native->use_modifiers ? "enabled" : "disabled"); - } - else - { - if (!create_renderer_gpu_data (renderer_native, NULL, error)) - return FALSE; - } - - return TRUE; -} - -static void -initable_iface_init (GInitableIface *initable_iface) -{ - initable_iface->init = meta_renderer_native_initable_init; -} - -static void -meta_renderer_native_finalize (GObject *object) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object); - - clear_kept_alive_onscreens (renderer_native); - - g_clear_list (&renderer_native->power_save_page_flip_onscreens, - g_object_unref); - g_clear_handle_id (&renderer_native->power_save_page_flip_source_id, - g_source_remove); - - g_list_free (renderer_native->pending_mode_set_views); - - g_hash_table_destroy (renderer_native->gpu_datas); - g_clear_object (&renderer_native->gles3); - - G_OBJECT_CLASS (meta_renderer_native_parent_class)->finalize (object); -} - -static void -meta_renderer_native_constructed (GObject *object) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object); - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaSettings *settings = meta_backend_get_settings (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - if (meta_settings_is_experimental_feature_enabled ( - settings, META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS)) - renderer_native->use_modifiers = TRUE; - - g_signal_connect (backend, "gpu-added", - G_CALLBACK (on_gpu_added), renderer_native); - g_signal_connect (monitor_manager, "power-save-mode-changed", - G_CALLBACK (on_power_save_mode_changed), renderer_native); - - G_OBJECT_CLASS (meta_renderer_native_parent_class)->constructed (object); -} - -static void -meta_renderer_native_init (MetaRendererNative *renderer_native) -{ - renderer_native->gpu_datas = - g_hash_table_new_full (NULL, NULL, - NULL, - (GDestroyNotify) meta_renderer_native_gpu_data_free); -} - -static void -meta_renderer_native_class_init (MetaRendererNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaRendererClass *renderer_class = META_RENDERER_CLASS (klass); - - object_class->finalize = meta_renderer_native_finalize; - object_class->constructed = meta_renderer_native_constructed; - - renderer_class->create_cogl_renderer = meta_renderer_native_create_cogl_renderer; - renderer_class->create_view = meta_renderer_native_create_view; - renderer_class->rebuild_views = meta_renderer_native_rebuild_views; -} - -MetaRendererNative * -meta_renderer_native_new (MetaBackendNative *backend_native, - GError **error) -{ - return g_initable_new (META_TYPE_RENDERER_NATIVE, - NULL, - error, - "backend", backend_native, - NULL); -} diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h deleted file mode 100644 index 2c23c651a..000000000 --- a/src/backends/native/meta-renderer-native.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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: - * Jonas Ådahl <jadahl@gmail.com> - */ - -#ifndef META_RENDERER_NATIVE_H -#define META_RENDERER_NATIVE_H - -#include <gbm.h> -#include <glib-object.h> -#include <xf86drmMode.h> - -#include "backends/meta-renderer.h" -#include "backends/native/meta-gpu-kms.h" -#include "backends/native/meta-monitor-manager-native.h" - -#define META_TYPE_RENDERER_NATIVE (meta_renderer_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaRendererNative, meta_renderer_native, - META, RENDERER_NATIVE, - MetaRenderer) - -typedef enum _MetaRendererNativeMode -{ - META_RENDERER_NATIVE_MODE_GBM, - META_RENDERER_NATIVE_MODE_SURFACELESS, -#ifdef HAVE_EGL_DEVICE - META_RENDERER_NATIVE_MODE_EGL_DEVICE -#endif -} MetaRendererNativeMode; - -MetaRendererNative * meta_renderer_native_new (MetaBackendNative *backend_native, - GError **error); - -struct gbm_device * meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms); - -MetaGpuKms * meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_native); - -MetaDeviceFile * meta_renderer_native_get_primary_device_file (MetaRendererNative *renderer_native); - -void meta_renderer_native_prepare_frame (MetaRendererNative *renderer_native, - MetaRendererView *view, - ClutterFrame *frame); - -void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native, - MetaRendererView *view, - ClutterFrame *frame); - -void meta_renderer_native_reset_modes (MetaRendererNative *renderer_native); - -gboolean meta_renderer_native_use_modifiers (MetaRendererNative *renderer_native); - -#endif /* META_RENDERER_NATIVE_H */ diff --git a/src/backends/native/meta-seat-impl.c b/src/backends/native/meta-seat-impl.c deleted file mode 100644 index 26db30bd4..000000000 --- a/src/backends/native/meta-seat-impl.c +++ /dev/null @@ -1,3542 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * Copyright (C) 2016 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Damien Lespiau <damien.lespiau@intel.com> - * Author: Jonas Ådahl <jadahl@gmail.com> - * Author: Carlos Garnacho <carlosg@gnome.org> - */ - -#include "config.h" - -#include <errno.h> -#include <fcntl.h> -#include <libinput.h> -#include <linux/input.h> -#include <math.h> - -#include "backends/meta-cursor-tracker-private.h" -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-barrier-native.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-virtual-input-device-native.h" -#include "clutter/clutter-mutter.h" -#include "core/bell.h" - -#include "meta-private-enum-types.h" - -/* - * Clutter makes the assumption that two core devices have ID's 2 and 3 (core - * pointer and core keyboard). - * - * Since the two first devices that will ever be created will be the virtual - * pointer and virtual keyboard of the first seat, we fulfill the made - * assumptions by having the first device having ID 2 and following 3. - */ -#define INITIAL_DEVICE_ID 2 - -/* Try to keep the pointer inside the stage. Hopefully no one is using - * this backend with stages smaller than this. */ -#define INITIAL_POINTER_X 16 -#define INITIAL_POINTER_Y 16 - -#define AUTOREPEAT_VALUE 2 - -#define DISCRETE_SCROLL_STEP 10.0 - -#ifndef BTN_STYLUS3 -#define BTN_STYLUS3 0x149 /* Linux 4.15 */ -#endif - -struct _MetaEventSource -{ - GSource source; - - MetaSeatImpl *seat_impl; - GPollFD event_poll_fd; -}; - -enum -{ - PROP_0, - PROP_SEAT, - PROP_SEAT_ID, - PROP_FLAGS, - N_PROPS, -}; - -static GParamSpec *props[N_PROPS] = { NULL }; - -enum -{ - KBD_A11Y_FLAGS_CHANGED, - KBD_A11Y_MODS_STATE_CHANGED, - TOUCH_MODE, - BELL, - MODS_STATE_CHANGED, - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - -typedef struct _MetaSeatImplPrivate -{ - GHashTable *device_files; -} MetaSeatImplPrivate; - -static void meta_seat_impl_initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaSeatImpl, meta_seat_impl, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - meta_seat_impl_initable_iface_init) - G_ADD_PRIVATE (MetaSeatImpl)) - -static void process_events (MetaSeatImpl *seat_impl); -void meta_seat_impl_constrain_pointer (MetaSeatImpl *seat_impl, - ClutterInputDevice *core_pointer, - uint64_t time_us, - float x, - float y, - float *new_x, - float *new_y); -void meta_seat_impl_filter_relative_motion (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - float x, - float y, - float *dx, - float *dy); -void meta_seat_impl_clear_repeat_source (MetaSeatImpl *seat_impl); - -void -meta_seat_impl_run_input_task (MetaSeatImpl *seat_impl, - GTask *task, - GSourceFunc dispatch_func) -{ - GSource *source; - - source = g_idle_source_new (); - g_source_set_priority (source, G_PRIORITY_HIGH); - g_source_set_callback (source, - dispatch_func, - g_object_ref (task), - g_object_unref); - g_source_attach (source, seat_impl->input_context); - g_source_unref (source); -} - -void -meta_seat_impl_sync_leds_in_impl (MetaSeatImpl *seat_impl) -{ - GSList *iter; - MetaInputDeviceNative *device_native; - int caps_lock, num_lock, scroll_lock; - enum libinput_led leds = 0; - - caps_lock = xkb_state_led_index_is_active (seat_impl->xkb, - seat_impl->caps_lock_led); - num_lock = xkb_state_led_index_is_active (seat_impl->xkb, - seat_impl->num_lock_led); - scroll_lock = xkb_state_led_index_is_active (seat_impl->xkb, - seat_impl->scroll_lock_led); - - if (caps_lock) - leds |= LIBINPUT_LED_CAPS_LOCK; - if (num_lock) - leds |= LIBINPUT_LED_NUM_LOCK; - if (scroll_lock) - leds |= LIBINPUT_LED_SCROLL_LOCK; - - for (iter = seat_impl->devices; iter; iter = iter->next) - { - device_native = iter->data; - meta_input_device_native_update_leds_in_impl (device_native, leds); - } -} - -MetaTouchState * -meta_seat_impl_lookup_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot) -{ - if (!seat_impl->touch_states) - return NULL; - - return g_hash_table_lookup (seat_impl->touch_states, - GINT_TO_POINTER (seat_slot)); -} - -static void -meta_touch_state_free (MetaTouchState *state) -{ - g_free (state); -} - -MetaTouchState * -meta_seat_impl_acquire_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot) -{ - MetaTouchState *touch_state; - - if (!seat_impl->touch_states) - { - seat_impl->touch_states = - g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) meta_touch_state_free); - } - - g_assert (!g_hash_table_contains (seat_impl->touch_states, - GINT_TO_POINTER (seat_slot))); - - touch_state = g_new0 (MetaTouchState, 1); - *touch_state = (MetaTouchState) { - .seat_impl = seat_impl, - .seat_slot = seat_slot, - }; - - g_hash_table_insert (seat_impl->touch_states, GINT_TO_POINTER (seat_slot), - touch_state); - - return touch_state; -} - -void -meta_seat_impl_release_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot) -{ - if (!seat_impl->touch_states) - return; - g_hash_table_remove (seat_impl->touch_states, GINT_TO_POINTER (seat_slot)); -} - -void -meta_seat_impl_clear_repeat_source (MetaSeatImpl *seat_impl) -{ - if (seat_impl->repeat_source) - { - g_source_destroy (seat_impl->repeat_source); - g_clear_pointer (&seat_impl->repeat_source, g_source_unref); - } - - g_clear_object (&seat_impl->repeat_device); -} - -static void -dispatch_libinput (MetaSeatImpl *seat_impl) -{ - libinput_dispatch (seat_impl->libinput); - process_events (seat_impl); -} - -static gboolean -keyboard_repeat (gpointer data) -{ - MetaSeatImpl *seat_impl = data; - - /* There might be events queued in libinput that could cancel the - repeat timer. */ - if (seat_impl->libinput) - { - dispatch_libinput (seat_impl); - if (!seat_impl->repeat_source) - return G_SOURCE_REMOVE; - } - - g_return_val_if_fail (seat_impl->repeat_device != NULL, G_SOURCE_REMOVE); - - meta_seat_impl_notify_key_in_impl (seat_impl, - seat_impl->repeat_device, - g_source_get_time (seat_impl->repeat_source), - seat_impl->repeat_key, - AUTOREPEAT_VALUE, - FALSE); - - return G_SOURCE_CONTINUE; -} - -static void -queue_event (MetaSeatImpl *seat_impl, - ClutterEvent *event) -{ - _clutter_event_push (event, FALSE); -} - -static int -update_button_count (MetaSeatImpl *seat_impl, - uint32_t button, - uint32_t state) -{ - if (state) - { - return ++seat_impl->button_count[button]; - } - else - { - /* Handle cases where we newer saw the initial pressed event. */ - if (seat_impl->button_count[button] == 0) - { - meta_topic (META_DEBUG_INPUT, - "Counting release of key 0x%x and count is already 0", - button); - return 0; - } - - return --seat_impl->button_count[button]; - } -} - -void -meta_seat_impl_queue_main_thread_idle (MetaSeatImpl *seat_impl, - GSourceFunc func, - gpointer user_data, - GDestroyNotify destroy_notify) -{ - GSource *source; - - source = g_idle_source_new (); - g_source_set_priority (source, G_PRIORITY_HIGH); - g_source_set_callback (source, func, user_data, destroy_notify); - - g_source_attach (source, seat_impl->main_context); - g_source_unref (source); -} - -typedef struct -{ - MetaSeatImpl *seat_impl; - guint signal_id; - GArray *args; -} MetaSeatSignalData; - -static gboolean -emit_signal_in_main (MetaSeatSignalData *data) -{ - g_signal_emitv ((GValue *) data->args->data, - data->signal_id, - 0, NULL); - - return G_SOURCE_REMOVE; -} - -static void -signal_data_free (MetaSeatSignalData *data) -{ - g_array_unref (data->args); - g_free (data); -} - -static void -emit_signal (MetaSeatImpl *seat_impl, - guint signal_id, - GValue *args, - int n_args) -{ - MetaSeatSignalData *emit_signal_data; - GArray *array; - GValue self = G_VALUE_INIT; - - g_value_init (&self, META_TYPE_SEAT_IMPL); - g_value_set_object (&self, seat_impl); - - array = g_array_new (FALSE, FALSE, sizeof (GValue)); - g_array_append_val (array, self); - if (args && n_args > 0) - g_array_append_vals (array, args, n_args); - - emit_signal_data = g_new0 (MetaSeatSignalData, 1); - emit_signal_data->seat_impl = seat_impl; - emit_signal_data->signal_id = signal_id; - emit_signal_data->args = array; - - meta_seat_impl_queue_main_thread_idle (seat_impl, - (GSourceFunc) emit_signal_in_main, - emit_signal_data, - (GDestroyNotify) signal_data_free); -} - -void -meta_seat_impl_notify_key_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint64_t time_us, - uint32_t key, - uint32_t state, - gboolean update_keys) -{ - ClutterEvent *event = NULL; - enum xkb_state_component changed_state; - uint32_t keycode; - - if (state != AUTOREPEAT_VALUE) - { - /* Drop any repeated button press (for example from virtual devices. */ - int count = update_button_count (seat_impl, key, state); - if ((state && count > 1) || - (!state && count != 0)) - { - meta_topic (META_DEBUG_INPUT, - "Dropping repeated %s of key 0x%x, count %d, state %d", - state ? "press" : "release", key, count, state); - return; - } - } - - event = meta_key_event_new_from_evdev (device, - seat_impl->core_keyboard, - seat_impl->xkb, - seat_impl->button_state, - us2ms (time_us), key, state); - event->key.evdev_code = key; - - keycode = meta_xkb_evdev_to_keycode (key); - - /* We must be careful and not pass multiple releases to xkb, otherwise it gets - confused and locks the modifiers */ - if (state != AUTOREPEAT_VALUE) - { - changed_state = xkb_state_update_key (seat_impl->xkb, keycode, - state ? XKB_KEY_DOWN : XKB_KEY_UP); - } - else - { - changed_state = 0; - clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_REPEATED); - } - - if (!meta_input_device_native_process_kbd_a11y_event_in_impl (seat_impl->core_keyboard, - event)) - queue_event (seat_impl, event); - else - clutter_event_free (event); - - if (update_keys && (changed_state & XKB_STATE_LEDS)) - { - MetaInputDeviceNative *keyboard_native; - gboolean numlock_active; - - meta_keymap_native_update_in_impl (seat_impl->keymap, - seat_impl, - seat_impl->xkb); - meta_seat_impl_sync_leds_in_impl (seat_impl); - - numlock_active = - xkb_state_mod_name_is_active (seat_impl->xkb, XKB_MOD_NAME_NUM, - XKB_STATE_MODS_LATCHED | - XKB_STATE_MODS_LOCKED); - meta_input_settings_maybe_save_numlock_state (seat_impl->input_settings, - numlock_active); - - keyboard_native = META_INPUT_DEVICE_NATIVE (seat_impl->core_keyboard); - meta_input_device_native_a11y_maybe_notify_toggle_keys_in_impl (keyboard_native); - } - - if (state == 0 || /* key release */ - !seat_impl->repeat || - !xkb_keymap_key_repeats (xkb_state_get_keymap (seat_impl->xkb), - keycode)) - { - seat_impl->repeat_count = 0; - meta_seat_impl_clear_repeat_source (seat_impl); - return; - } - - if (state == 1) /* key press */ - seat_impl->repeat_count = 0; - - seat_impl->repeat_count += 1; - seat_impl->repeat_key = key; - - switch (seat_impl->repeat_count) - { - case 1: - case 2: - { - uint32_t interval; - - meta_seat_impl_clear_repeat_source (seat_impl); - seat_impl->repeat_device = g_object_ref (device); - - if (seat_impl->repeat_count == 1) - interval = seat_impl->repeat_delay; - else - interval = seat_impl->repeat_interval; - - seat_impl->repeat_source = g_timeout_source_new (interval); - g_source_set_priority (seat_impl->repeat_source, CLUTTER_PRIORITY_EVENTS); - g_source_set_callback (seat_impl->repeat_source, - keyboard_repeat, seat_impl, NULL); - g_source_attach (seat_impl->repeat_source, seat_impl->input_context); - return; - } - default: - return; - } -} - -static ClutterEvent * -new_absolute_motion_event (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - float x, - float y, - double *axes) -{ - ClutterEvent *event; - - event = clutter_event_new (CLUTTER_MOTION); - - if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE) - { - meta_seat_impl_constrain_pointer (seat_impl, - seat_impl->core_pointer, - time_us, - seat_impl->pointer_x, - seat_impl->pointer_y, - &x, &y); - } - else - { - /* This may happen early at startup */ - if (seat_impl->viewports) - { - meta_input_device_native_translate_coordinates_in_impl (input_device, - seat_impl->viewports, - &x, - &y); - } - } - - event->motion.time_us = time_us; - event->motion.time = us2ms (time_us); - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - event->motion.x = x; - event->motion.y = y; - - event->motion.axes = axes; - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - g_rw_lock_writer_lock (&seat_impl->state_lock); - - if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) - { - MetaInputDeviceNative *device_native = - META_INPUT_DEVICE_NATIVE (input_device); - - clutter_event_set_device_tool (event, device_native->last_tool); - clutter_event_set_device (event, input_device); - meta_input_device_native_set_coords_in_impl (META_INPUT_DEVICE_NATIVE (input_device), - x, y); - } - else - { - clutter_event_set_device (event, seat_impl->core_pointer); - meta_input_device_native_set_coords_in_impl (META_INPUT_DEVICE_NATIVE (seat_impl->core_pointer), - x, y); - } - - if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE) - { - seat_impl->pointer_x = x; - seat_impl->pointer_y = y; - } - - g_rw_lock_writer_unlock (&seat_impl->state_lock); - - return event; -} - -void -meta_seat_impl_notify_relative_motion_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - float dx, - float dy, - float dx_unaccel, - float dy_unaccel) -{ - float new_x, new_y; - ClutterEvent *event; - - meta_seat_impl_filter_relative_motion (seat_impl, - input_device, - seat_impl->pointer_x, - seat_impl->pointer_y, - &dx, - &dy); - - new_x = seat_impl->pointer_x + dx; - new_y = seat_impl->pointer_y + dy; - event = new_absolute_motion_event (seat_impl, input_device, - time_us, new_x, new_y, NULL); - - event->motion.flags |= CLUTTER_EVENT_FLAG_RELATIVE_MOTION; - event->motion.dx = dx; - event->motion.dy = dy; - event->motion.dx_unaccel = dx_unaccel; - event->motion.dy_unaccel = dy_unaccel; - - queue_event (seat_impl, event); -} - -void -meta_seat_impl_notify_absolute_motion_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - float x, - float y, - double *axes) -{ - ClutterEvent *event; - - event = new_absolute_motion_event (seat_impl, input_device, time_us, x, y, axes); - - queue_event (seat_impl, event); -} - -void -meta_seat_impl_notify_button_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - uint32_t button, - uint32_t state) -{ - MetaInputDeviceNative *device_native = (MetaInputDeviceNative *) input_device; - ClutterEvent *event = NULL; - int button_nr; - static int maskmap[8] = - { - CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK, - CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0 - }; - int button_count; - - /* Drop any repeated button press (for example from virtual devices. */ - button_count = update_button_count (seat_impl, button, state); - if ((state && button_count > 1) || - (!state && button_count != 0)) - { - meta_topic (META_DEBUG_INPUT, - "Dropping repeated %s of button 0x%x, count %d", - state ? "press" : "release", button, button_count); - return; - } - - /* The evdev button numbers don't map sequentially to clutter button - * numbers (the right and middle mouse buttons are in the opposite - * order) so we'll map them directly with a switch statement */ - switch (button) - { - case BTN_LEFT: - case BTN_TOUCH: - button_nr = CLUTTER_BUTTON_PRIMARY; - break; - - case BTN_RIGHT: - case BTN_STYLUS: - button_nr = CLUTTER_BUTTON_SECONDARY; - break; - - case BTN_MIDDLE: - case BTN_STYLUS2: - button_nr = CLUTTER_BUTTON_MIDDLE; - break; - - case 0x149: /* BTN_STYLUS3 */ - button_nr = 8; - break; - - default: - /* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */ - if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) - button_nr = button - BTN_TOOL_PEN + 4; - else - button_nr = button - (BTN_LEFT - 1) + 4; - break; - } - - if (button_nr < 1 || button_nr > 12) - { - g_warning ("Unhandled button event 0x%x", button); - return; - } - - if (state) - event = clutter_event_new (CLUTTER_BUTTON_PRESS); - else - event = clutter_event_new (CLUTTER_BUTTON_RELEASE); - - if (button_nr < G_N_ELEMENTS (maskmap)) - { - /* Update the modifiers */ - if (state) - seat_impl->button_state |= maskmap[button_nr - 1]; - else - seat_impl->button_state &= ~maskmap[button_nr - 1]; - } - - event->button.time = us2ms (time_us); - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - event->button.button = button_nr; - - if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) - { - meta_input_device_native_get_coords_in_impl (device_native, - &event->button.x, - &event->button.y); - } - else - { - meta_input_device_native_get_coords_in_impl (META_INPUT_DEVICE_NATIVE (seat_impl->core_pointer), - &event->button.x, - &event->button.y); - } - - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - if (device_native->last_tool) - { - /* Apply the button event code as per the tool mapping */ - uint32_t mapped_button; - - mapped_button = meta_input_device_tool_native_get_button_code_in_impl (device_native->last_tool, - button_nr); - if (mapped_button != 0) - button = mapped_button; - } - - event->button.evdev_code = button; - - if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) - { - clutter_event_set_device_tool (event, device_native->last_tool); - clutter_event_set_device (event, input_device); - } - else - { - clutter_event_set_device (event, seat_impl->core_pointer); - } - - queue_event (seat_impl, event); -} - -static MetaSeatImpl * -seat_impl_from_device (ClutterInputDevice *device) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - - return meta_input_device_native_get_seat_impl (device_native); -} - -static void -notify_scroll (ClutterInputDevice *input_device, - uint64_t time_us, - double dx, - double dy, - ClutterScrollSource scroll_source, - ClutterScrollFinishFlags flags, - gboolean emulated) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event = NULL; - double scroll_factor; - - seat_impl = seat_impl_from_device (input_device); - - event = clutter_event_new (CLUTTER_SCROLL); - - event->scroll.time = us2ms (time_us); - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - - /* libinput pointer axis events are in pointer motion coordinate space. - * To convert to Xi2 discrete step coordinate space, multiply the factor - * 1/10. */ - event->scroll.direction = CLUTTER_SCROLL_SMOOTH; - scroll_factor = 1.0 / DISCRETE_SCROLL_STEP; - clutter_event_set_scroll_delta (event, - scroll_factor * dx, - scroll_factor * dy); - - event->scroll.x = seat_impl->pointer_x; - event->scroll.y = seat_impl->pointer_y; - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - event->scroll.scroll_source = scroll_source; - event->scroll.finish_flags = flags; - - _clutter_event_set_pointer_emulated (event, emulated); - - queue_event (seat_impl, event); -} - -static void -notify_discrete_scroll (ClutterInputDevice *input_device, - uint64_t time_us, - ClutterScrollDirection direction, - ClutterScrollSource scroll_source, - gboolean emulated) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event = NULL; - - if (direction == CLUTTER_SCROLL_SMOOTH) - return; - - seat_impl = seat_impl_from_device (input_device); - - event = clutter_event_new (CLUTTER_SCROLL); - - event->scroll.time = us2ms (time_us); - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - - event->scroll.direction = direction; - - event->scroll.x = seat_impl->pointer_x; - event->scroll.y = seat_impl->pointer_y; - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - event->scroll.scroll_source = scroll_source; - - _clutter_event_set_pointer_emulated (event, emulated); - - queue_event (seat_impl, event); -} - -static void -check_notify_discrete_scroll (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint64_t time_us, - ClutterScrollSource scroll_source) -{ - int i, n_xscrolls, n_yscrolls; - - n_xscrolls = floor ((fabs (seat_impl->accum_scroll_dx) + DBL_EPSILON) / - DISCRETE_SCROLL_STEP); - n_yscrolls = floor ((fabs (seat_impl->accum_scroll_dy) + DBL_EPSILON) / - DISCRETE_SCROLL_STEP); - - for (i = 0; i < n_xscrolls; i++) - { - notify_discrete_scroll (device, time_us, - seat_impl->accum_scroll_dx > 0 ? - CLUTTER_SCROLL_RIGHT : CLUTTER_SCROLL_LEFT, - scroll_source, TRUE); - } - - for (i = 0; i < n_yscrolls; i++) - { - notify_discrete_scroll (device, time_us, - seat_impl->accum_scroll_dy > 0 ? - CLUTTER_SCROLL_DOWN : CLUTTER_SCROLL_UP, - scroll_source, TRUE); - } - - seat_impl->accum_scroll_dx = - fmodf (seat_impl->accum_scroll_dx, DISCRETE_SCROLL_STEP); - seat_impl->accum_scroll_dy = - fmodf (seat_impl->accum_scroll_dy, DISCRETE_SCROLL_STEP); -} - -void -meta_seat_impl_notify_scroll_continuous_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - double dx, - double dy, - ClutterScrollSource scroll_source, - ClutterScrollFinishFlags finish_flags) -{ - if (finish_flags & CLUTTER_SCROLL_FINISHED_HORIZONTAL) - seat_impl->accum_scroll_dx = 0; - else - seat_impl->accum_scroll_dx += dx; - - if (finish_flags & CLUTTER_SCROLL_FINISHED_VERTICAL) - seat_impl->accum_scroll_dy = 0; - else - seat_impl->accum_scroll_dy += dy; - - notify_scroll (input_device, time_us, dx, dy, scroll_source, - finish_flags, FALSE); - check_notify_discrete_scroll (seat_impl, input_device, time_us, scroll_source); -} - -static ClutterScrollDirection -discrete_to_direction (double discrete_dx, - double discrete_dy) -{ - if (discrete_dx > 0) - return CLUTTER_SCROLL_RIGHT; - else if (discrete_dx < 0) - return CLUTTER_SCROLL_LEFT; - else if (discrete_dy > 0) - return CLUTTER_SCROLL_DOWN; - else if (discrete_dy < 0) - return CLUTTER_SCROLL_UP; - else - g_assert_not_reached (); - return 0; -} - -void -meta_seat_impl_notify_discrete_scroll_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - double discrete_dx, - double discrete_dy, - ClutterScrollSource scroll_source) -{ - notify_scroll (input_device, time_us, - discrete_dx * DISCRETE_SCROLL_STEP, - discrete_dy * DISCRETE_SCROLL_STEP, - scroll_source, CLUTTER_SCROLL_FINISHED_NONE, - TRUE); - notify_discrete_scroll (input_device, time_us, - discrete_to_direction (discrete_dx, discrete_dy), - scroll_source, FALSE); - -} - -void -meta_seat_impl_notify_touch_event_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - ClutterEventType evtype, - uint64_t time_us, - int slot, - double x, - double y) -{ - ClutterEvent *event = NULL; - - event = clutter_event_new (evtype); - - event->touch.time = us2ms (time_us); - event->touch.x = x; - event->touch.y = y; - meta_input_device_native_translate_coordinates_in_impl (input_device, - seat_impl->viewports, - &event->touch.x, - &event->touch.y); - - /* "NULL" sequences are special cased in clutter */ - event->touch.sequence = GINT_TO_POINTER (MAX (1, slot + 1)); - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - - if (evtype == CLUTTER_TOUCH_BEGIN || - evtype == CLUTTER_TOUCH_UPDATE) - event->touch.modifier_state |= CLUTTER_BUTTON1_MASK; - - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - queue_event (seat_impl, event); -} - -/* - * MetaEventSource for reading input devices - */ - -static gboolean -meta_event_prepare (GSource *g_source, - int *timeout_ms) -{ - MetaEventSource *source = (MetaEventSource *) g_source; - MetaSeatImpl *seat_impl = source->seat_impl; - - *timeout_ms = -1; - - switch (libinput_next_event_type (seat_impl->libinput)) - { - case LIBINPUT_EVENT_NONE: - return FALSE; - default: - return TRUE; - } -} - -static gboolean -meta_event_check (GSource *source) -{ - MetaEventSource *event_source = (MetaEventSource *) source; - gboolean retval; - - retval = !!(event_source->event_poll_fd.revents & G_IO_IN); - - return retval; -} - -static void -constrain_to_barriers (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint32_t time, - float *new_x, - float *new_y) -{ - meta_barrier_manager_native_process_in_impl (seat_impl->barrier_manager, - device, - time, - new_x, new_y); -} - -/* - * The pointer constrain code is mostly a rip-off of the XRandR code from Xorg. - * (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder) - * - * Copyright © 2006 Keith Packard - * Copyright 2010 Red Hat, Inc - * - */ - -static void -constrain_all_screen_monitors (ClutterInputDevice *device, - MetaViewportInfo *viewports, - float *x, - float *y) -{ - float cx, cy; - int i, n_views; - - meta_input_device_native_get_coords_in_impl (META_INPUT_DEVICE_NATIVE (device), - &cx, &cy); - - /* if we're trying to escape, clamp to the CRTC we're coming from */ - - n_views = meta_viewport_info_get_num_views (viewports); - - for (i = 0; i < n_views; i++) - { - int left, right, top, bottom; - cairo_rectangle_int_t rect; - - meta_viewport_info_get_view_info (viewports, i, &rect, NULL); - - left = rect.x; - right = left + rect.width; - top = rect.y; - bottom = top + rect.height; - - if ((cx >= left) && (cx < right) && (cy >= top) && (cy < bottom)) - { - if (*x < left) - *x = left; - if (*x >= right) - *x = right - 1; - if (*y < top) - *y = top; - if (*y >= bottom) - *y = bottom - 1; - - return; - } - } -} - -void -meta_seat_impl_constrain_pointer (MetaSeatImpl *seat_impl, - ClutterInputDevice *core_pointer, - uint64_t time_us, - float x, - float y, - float *new_x, - float *new_y) -{ - /* Constrain to barriers */ - constrain_to_barriers (seat_impl, core_pointer, - us2ms (time_us), - new_x, new_y); - - /* Bar to constraints */ - if (seat_impl->pointer_constraint) - { - meta_pointer_constraint_impl_constrain (seat_impl->pointer_constraint, - core_pointer, - us2ms (time_us), - x, y, - new_x, new_y); - } - - if (seat_impl->viewports) - { - /* if we're moving inside a monitor, we're fine */ - if (meta_viewport_info_get_view_at (seat_impl->viewports, - *new_x, *new_y) >= 0) - return; - - /* if we're trying to escape, clamp to the CRTC we're coming from */ - constrain_all_screen_monitors (core_pointer, seat_impl->viewports, - new_x, new_y); - } -} - -static void -relative_motion_across_outputs (MetaViewportInfo *viewports, - int view, - float cur_x, - float cur_y, - float *dx_inout, - float *dy_inout) -{ - int cur_view = view; - float x = cur_x, y = cur_y; - float target_x = cur_x, target_y = cur_y; - float dx = *dx_inout, dy = *dy_inout; - MetaDisplayDirection direction = -1; - - while (cur_view >= 0) - { - MetaLine2 left, right, top, bottom, motion; - MetaVector2 intersection; - cairo_rectangle_int_t rect; - float scale; - - meta_viewport_info_get_view_info (viewports, cur_view, &rect, &scale); - - motion = (MetaLine2) { - .a = { x, y }, - .b = { x + (dx * scale), y + (dy * scale) } - }; - left = (MetaLine2) { - { rect.x, rect.y }, - { rect.x, rect.y + rect.height } - }; - right = (MetaLine2) { - { rect.x + rect.width, rect.y }, - { rect.x + rect.width, rect.y + rect.height } - }; - top = (MetaLine2) { - { rect.x, rect.y }, - { rect.x + rect.width, rect.y } - }; - bottom = (MetaLine2) { - { rect.x, rect.y + rect.height }, - { rect.x + rect.width, rect.y + rect.height } - }; - - target_x = motion.b.x; - target_y = motion.b.y; - - if (direction != META_DISPLAY_RIGHT && - meta_line2_intersects_with (&motion, &left, &intersection)) - direction = META_DISPLAY_LEFT; - else if (direction != META_DISPLAY_LEFT && - meta_line2_intersects_with (&motion, &right, &intersection)) - direction = META_DISPLAY_RIGHT; - else if (direction != META_DISPLAY_DOWN && - meta_line2_intersects_with (&motion, &top, &intersection)) - direction = META_DISPLAY_UP; - else if (direction != META_DISPLAY_UP && - meta_line2_intersects_with (&motion, &bottom, &intersection)) - direction = META_DISPLAY_DOWN; - else - /* We reached the dest logical monitor */ - break; - - x = intersection.x; - y = intersection.y; - dx -= intersection.x - motion.a.x; - dy -= intersection.y - motion.a.y; - - cur_view = meta_viewport_info_get_neighbor (viewports, cur_view, - direction); - } - - *dx_inout = target_x - cur_x; - *dy_inout = target_y - cur_y; -} - -void -meta_seat_impl_filter_relative_motion (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - float x, - float y, - float *dx, - float *dy) -{ - int view, dest_view; - float new_dx, new_dy, scale; - - if (!seat_impl->viewports) - return; - if (meta_viewport_info_is_views_scaled (seat_impl->viewports)) - return; - - view = meta_viewport_info_get_view_at (seat_impl->viewports, x, y); - if (view < 0) - return; - - meta_viewport_info_get_view_info (seat_impl->viewports, view, NULL, &scale); - new_dx = (*dx) * scale; - new_dy = (*dy) * scale; - - dest_view = meta_viewport_info_get_view_at (seat_impl->viewports, - x + new_dx, - y + new_dy); - if (dest_view >= 0 && dest_view != view) - { - /* If we are crossing monitors, attempt to bisect the distance on each - * axis and apply the relative scale for each of them. - */ - new_dx = *dx; - new_dy = *dy; - relative_motion_across_outputs (seat_impl->viewports, view, - x, y, &new_dx, &new_dy); - } - - *dx = new_dx; - *dy = new_dy; -} - -static void -notify_absolute_motion_in_impl (ClutterInputDevice *input_device, - uint64_t time_us, - float x, - float y, - double *axes) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event; - - seat_impl = seat_impl_from_device (input_device); - event = new_absolute_motion_event (seat_impl, input_device, time_us, x, y, axes); - - queue_event (seat_impl, event); -} - -static void -notify_relative_tool_motion_in_impl (ClutterInputDevice *input_device, - uint64_t time_us, - float dx, - float dy, - double *axes) -{ - MetaInputDeviceNative *device_native; - ClutterEvent *event; - MetaSeatImpl *seat_impl; - float x, y; - - device_native = META_INPUT_DEVICE_NATIVE (input_device); - seat_impl = seat_impl_from_device (input_device); - x = device_native->pointer_x + dx; - y = device_native->pointer_y + dy; - - meta_seat_impl_filter_relative_motion (seat_impl, - input_device, - seat_impl->pointer_x, - seat_impl->pointer_y, - &dx, - &dy); - - event = new_absolute_motion_event (seat_impl, input_device, time_us, - x, y, axes); - - event->motion.flags |= CLUTTER_EVENT_FLAG_RELATIVE_MOTION; - event->motion.dx = dx; - event->motion.dy = dy; - - queue_event (seat_impl, event); -} - -static void -notify_pinch_gesture_event (ClutterInputDevice *input_device, - ClutterTouchpadGesturePhase phase, - uint64_t time_us, - double dx, - double dy, - double dx_unaccel, - double dy_unaccel, - double angle_delta, - double scale, - uint32_t n_fingers) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event = NULL; - - seat_impl = seat_impl_from_device (input_device); - - event = clutter_event_new (CLUTTER_TOUCHPAD_PINCH); - - meta_input_device_native_get_coords_in_impl (META_INPUT_DEVICE_NATIVE (seat_impl->core_pointer), - &event->touchpad_pinch.x, - &event->touchpad_pinch.y); - - event->touchpad_pinch.phase = phase; - event->touchpad_pinch.time = us2ms (time_us); - event->touchpad_pinch.dx = dx; - event->touchpad_pinch.dy = dy; - event->touchpad_pinch.dx_unaccel = dx_unaccel; - event->touchpad_pinch.dy_unaccel = dy_unaccel; - event->touchpad_pinch.angle_delta = angle_delta; - event->touchpad_pinch.scale = scale; - event->touchpad_pinch.n_fingers = n_fingers; - - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - queue_event (seat_impl, event); -} - -static void -notify_swipe_gesture_event (ClutterInputDevice *input_device, - ClutterTouchpadGesturePhase phase, - uint64_t time_us, - uint32_t n_fingers, - double dx, - double dy, - double dx_unaccel, - double dy_unaccel) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event = NULL; - - seat_impl = seat_impl_from_device (input_device); - - event = clutter_event_new (CLUTTER_TOUCHPAD_SWIPE); - - event->touchpad_swipe.phase = phase; - event->touchpad_swipe.time = us2ms (time_us); - - meta_input_device_native_get_coords_in_impl (META_INPUT_DEVICE_NATIVE (seat_impl->core_pointer), - &event->touchpad_swipe.x, - &event->touchpad_swipe.y); - event->touchpad_swipe.dx = dx; - event->touchpad_swipe.dy = dy; - event->touchpad_swipe.dx_unaccel = dx_unaccel; - event->touchpad_swipe.dy_unaccel = dy_unaccel; - event->touchpad_swipe.n_fingers = n_fingers; - - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - queue_event (seat_impl, event); -} - -static void -notify_proximity (ClutterInputDevice *input_device, - uint64_t time_us, - gboolean in) -{ - MetaInputDeviceNative *device_native; - MetaSeatImpl *seat_impl; - ClutterEvent *event = NULL; - - device_native = META_INPUT_DEVICE_NATIVE (input_device); - seat_impl = seat_impl_from_device (input_device); - - if (in) - event = clutter_event_new (CLUTTER_PROXIMITY_IN); - else - event = clutter_event_new (CLUTTER_PROXIMITY_OUT); - - event->proximity.time = us2ms (time_us); - clutter_event_set_device_tool (event, device_native->last_tool); - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - queue_event (seat_impl, event); -} - -static void -notify_pad_button (ClutterInputDevice *input_device, - uint64_t time_us, - uint32_t button, - uint32_t mode_group, - uint32_t mode, - uint32_t pressed) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event; - - seat_impl = seat_impl_from_device (input_device); - - if (pressed) - event = clutter_event_new (CLUTTER_PAD_BUTTON_PRESS); - else - event = clutter_event_new (CLUTTER_PAD_BUTTON_RELEASE); - - event->pad_button.button = button; - event->pad_button.group = mode_group; - event->pad_button.mode = mode; - clutter_event_set_device (event, input_device); - clutter_event_set_source_device (event, input_device); - clutter_event_set_time (event, us2ms (time_us)); - - queue_event (seat_impl, event); -} - -static void -notify_pad_strip (ClutterInputDevice *input_device, - uint64_t time_us, - uint32_t strip_number, - uint32_t strip_source, - uint32_t mode_group, - uint32_t mode, - double value) -{ - ClutterInputDevicePadSource source; - MetaSeatImpl *seat_impl; - ClutterEvent *event; - - seat_impl = seat_impl_from_device (input_device); - - if (strip_source == LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER) - source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER; - else - source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN; - - event = clutter_event_new (CLUTTER_PAD_STRIP); - event->pad_strip.strip_source = source; - event->pad_strip.strip_number = strip_number; - event->pad_strip.value = value; - event->pad_strip.group = mode_group; - event->pad_strip.mode = mode; - clutter_event_set_device (event, input_device); - clutter_event_set_source_device (event, input_device); - clutter_event_set_time (event, us2ms (time_us)); - - queue_event (seat_impl, event); -} - -static void -notify_pad_ring (ClutterInputDevice *input_device, - uint64_t time_us, - uint32_t ring_number, - uint32_t ring_source, - uint32_t mode_group, - uint32_t mode, - double angle) -{ - ClutterInputDevicePadSource source; - MetaSeatImpl *seat_impl; - ClutterEvent *event; - - seat_impl = seat_impl_from_device (input_device); - - if (ring_source == LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER) - source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER; - else - source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN; - - event = clutter_event_new (CLUTTER_PAD_RING); - event->pad_ring.ring_source = source; - event->pad_ring.ring_number = ring_number; - event->pad_ring.angle = angle; - event->pad_ring.group = mode_group; - event->pad_ring.mode = mode; - clutter_event_set_device (event, input_device); - clutter_event_set_source_device (event, input_device); - clutter_event_set_time (event, us2ms (time_us)); - - queue_event (seat_impl, event); -} - -static gboolean -meta_event_dispatch (GSource *g_source, - GSourceFunc callback, - gpointer user_data) -{ - MetaEventSource *source = (MetaEventSource *) g_source; - MetaSeatImpl *seat_impl; - - seat_impl = source->seat_impl; - - dispatch_libinput (seat_impl); - - return TRUE; -} - -static GSourceFuncs event_funcs = { - meta_event_prepare, - meta_event_check, - meta_event_dispatch, - NULL -}; - -static MetaEventSource * -meta_event_source_new (MetaSeatImpl *seat_impl) -{ - GSource *source; - MetaEventSource *event_source; - int fd; - - source = g_source_new (&event_funcs, sizeof (MetaEventSource)); - event_source = (MetaEventSource *) source; - - /* setup the source */ - event_source->seat_impl = seat_impl; - - fd = libinput_get_fd (seat_impl->libinput); - event_source->event_poll_fd.fd = fd; - event_source->event_poll_fd.events = G_IO_IN; - - /* and finally configure and attach the GSource */ - g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS); - g_source_add_poll (source, &event_source->event_poll_fd); - g_source_set_can_recurse (source, TRUE); - g_source_attach (source, seat_impl->input_context); - - return event_source; -} - -static void -meta_event_source_free (MetaEventSource *source) -{ - GSource *g_source = (GSource *) source; - - /* ignore the return value of close, it's not like we can do something - * about it */ - close (source->event_poll_fd.fd); - - g_source_destroy (g_source); - g_source_unref (g_source); -} - -static gboolean -has_touchscreen (MetaSeatImpl *seat_impl) -{ - GSList *l; - - for (l = seat_impl->devices; l; l = l->next) - { - ClutterInputDeviceType device_type; - - device_type = clutter_input_device_get_device_type (l->data); - - if (device_type == CLUTTER_TOUCHSCREEN_DEVICE) - return TRUE; - } - - return FALSE; -} - -static inline gboolean -device_type_is_pointer (ClutterInputDeviceType device_type) -{ - return device_type == CLUTTER_POINTER_DEVICE || - device_type == CLUTTER_TOUCHPAD_DEVICE; -} - -static gboolean -has_pointer (MetaSeatImpl *seat_impl) -{ - GSList *l; - - for (l = seat_impl->devices; l; l = l->next) - { - ClutterInputDeviceType device_type; - - device_type = clutter_input_device_get_device_type (l->data); - if (device_type_is_pointer (device_type)) - return TRUE; - } - - return FALSE; -} - -static gboolean -device_is_tablet_switch (MetaInputDeviceNative *device_native) -{ - if (libinput_device_has_capability (device_native->libinput_device, - LIBINPUT_DEVICE_CAP_SWITCH) && - libinput_device_switch_has_switch (device_native->libinput_device, - LIBINPUT_SWITCH_TABLET_MODE)) - return TRUE; - - return FALSE; -} - -static gboolean -has_tablet_switch (MetaSeatImpl *seat_impl) -{ - GSList *l; - - for (l = seat_impl->devices; l; l = l->next) - { - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (l->data); - - if (device_is_tablet_switch (device_native)) - return TRUE; - } - - return FALSE; -} - -static void -update_touch_mode (MetaSeatImpl *seat_impl) -{ - gboolean touch_mode; - - /* No touch mode if we don't have a touchscreen, easy */ - if (!seat_impl->has_touchscreen) - touch_mode = FALSE; - /* If we have a tablet mode switch, honor it being unset */ - else if (seat_impl->has_tablet_switch && !seat_impl->tablet_mode_switch_state) - touch_mode = FALSE; - /* If tablet mode is enabled, go for it */ - else if (seat_impl->has_tablet_switch && seat_impl->tablet_mode_switch_state) - touch_mode = TRUE; - /* If there is no tablet mode switch (eg. kiosk machines), - * assume touch-mode is mutually exclusive with pointers. - */ - else - touch_mode = !seat_impl->has_pointer; - - if (seat_impl->touch_mode != touch_mode) - { - GValue value = G_VALUE_INIT; - - g_value_init (&value, G_TYPE_BOOLEAN); - g_value_set_boolean (&value, touch_mode); - seat_impl->touch_mode = touch_mode; - emit_signal (seat_impl, signals[TOUCH_MODE], &value, 1); - g_value_unset (&value); - } -} - -static ClutterInputDevice * -evdev_add_device (MetaSeatImpl *seat_impl, - struct libinput_device *libinput_device) -{ - ClutterInputDeviceType type; - ClutterInputDevice *device; - gboolean is_touchscreen, is_tablet_switch, is_pointer; - - device = meta_input_device_native_new_in_impl (seat_impl, libinput_device); - - seat_impl->devices = g_slist_prepend (seat_impl->devices, device); - meta_seat_impl_sync_leds_in_impl (seat_impl); - - /* Clutter assumes that device types are exclusive in the - * ClutterInputDevice API */ - type = meta_input_device_native_determine_type_in_impl (libinput_device); - - is_touchscreen = type == CLUTTER_TOUCHSCREEN_DEVICE; - is_tablet_switch = - device_is_tablet_switch (META_INPUT_DEVICE_NATIVE (device)); - is_pointer = device_type_is_pointer (type); - - seat_impl->has_touchscreen |= is_touchscreen; - seat_impl->has_tablet_switch |= is_tablet_switch; - seat_impl->has_pointer |= is_pointer; - - if (is_touchscreen || is_tablet_switch || is_pointer) - update_touch_mode (seat_impl); - - return device; -} - -static void -evdev_remove_device (MetaSeatImpl *seat_impl, - MetaInputDeviceNative *device_native) -{ - ClutterInputDevice *device; - ClutterInputDeviceType device_type; - gboolean is_touchscreen, is_tablet_switch, is_pointer; - - device = CLUTTER_INPUT_DEVICE (device_native); - seat_impl->devices = g_slist_remove (seat_impl->devices, device); - - device_type = clutter_input_device_get_device_type (device); - - is_touchscreen = device_type == CLUTTER_TOUCHSCREEN_DEVICE; - is_tablet_switch = device_is_tablet_switch (device_native); - is_pointer = device_type_is_pointer (device_type); - - if (is_touchscreen) - seat_impl->has_touchscreen = has_touchscreen (seat_impl); - if (is_tablet_switch) - seat_impl->has_tablet_switch = has_tablet_switch (seat_impl); - if (is_pointer) - seat_impl->has_pointer = has_pointer (seat_impl); - - if (is_touchscreen || is_tablet_switch || is_pointer) - update_touch_mode (seat_impl); - - if (seat_impl->repeat_source && seat_impl->repeat_device == device) - meta_seat_impl_clear_repeat_source (seat_impl); - - meta_input_device_native_detach_libinput_in_impl (device_native); - - g_object_unref (device); -} - -static gboolean -process_base_event (MetaSeatImpl *seat_impl, - struct libinput_event *event) -{ - ClutterInputDevice *device; - ClutterEvent *device_event = NULL; - struct libinput_device *libinput_device; - MetaInputSettings *input_settings; - - input_settings = seat_impl->input_settings; - - switch (libinput_event_get_type (event)) - { - case LIBINPUT_EVENT_DEVICE_ADDED: - libinput_device = libinput_event_get_device (event); - - device = evdev_add_device (seat_impl, libinput_device); - device_event = clutter_event_new (CLUTTER_DEVICE_ADDED); - clutter_event_set_device (device_event, device); - meta_input_settings_add_device (input_settings, device); - break; - - case LIBINPUT_EVENT_DEVICE_REMOVED: - libinput_device = libinput_event_get_device (event); - - device = libinput_device_get_user_data (libinput_device); - device_event = clutter_event_new (CLUTTER_DEVICE_REMOVED); - clutter_event_set_device (device_event, device); - meta_input_settings_remove_device (input_settings, device); - evdev_remove_device (seat_impl, - META_INPUT_DEVICE_NATIVE (device)); - break; - - default: - break; - } - - if (device_event) - { - queue_event (seat_impl, device_event); - return TRUE; - } - - return FALSE; -} - -static ClutterScrollSource -translate_scroll_source (enum libinput_pointer_axis_source source) -{ - switch (source) - { - case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: - return CLUTTER_SCROLL_SOURCE_WHEEL; - case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: - return CLUTTER_SCROLL_SOURCE_FINGER; - case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: - return CLUTTER_SCROLL_SOURCE_CONTINUOUS; - default: - return CLUTTER_SCROLL_SOURCE_UNKNOWN; - } -} - -static ClutterInputDeviceToolType -translate_tool_type (struct libinput_tablet_tool *libinput_tool) -{ - enum libinput_tablet_tool_type tool; - - tool = libinput_tablet_tool_get_type (libinput_tool); - - switch (tool) - { - case LIBINPUT_TABLET_TOOL_TYPE_PEN: - return CLUTTER_INPUT_DEVICE_TOOL_PEN; - case LIBINPUT_TABLET_TOOL_TYPE_ERASER: - return CLUTTER_INPUT_DEVICE_TOOL_ERASER; - case LIBINPUT_TABLET_TOOL_TYPE_BRUSH: - return CLUTTER_INPUT_DEVICE_TOOL_BRUSH; - case LIBINPUT_TABLET_TOOL_TYPE_PENCIL: - return CLUTTER_INPUT_DEVICE_TOOL_PENCIL; - case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH: - return CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH; - case LIBINPUT_TABLET_TOOL_TYPE_MOUSE: - return CLUTTER_INPUT_DEVICE_TOOL_MOUSE; - case LIBINPUT_TABLET_TOOL_TYPE_LENS: - return CLUTTER_INPUT_DEVICE_TOOL_LENS; - default: - return CLUTTER_INPUT_DEVICE_TOOL_NONE; - } -} - -static void -input_device_update_tool (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - struct libinput_tablet_tool *libinput_tool) -{ - MetaInputDeviceNative *evdev_device = META_INPUT_DEVICE_NATIVE (input_device); - ClutterInputDeviceTool *tool = NULL; - MetaInputSettings *input_settings; - - if (libinput_tool) - { - if (!seat_impl->tools) - { - seat_impl->tools = - g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) g_object_unref); - } - - tool = g_hash_table_lookup (seat_impl->tools, libinput_tool); - - if (!tool) - { - ClutterInputDeviceToolType tool_type; - uint64_t tool_serial; - - tool_serial = libinput_tablet_tool_get_serial (libinput_tool); - tool_type = translate_tool_type (libinput_tool); - tool = meta_input_device_tool_native_new (libinput_tool, - tool_serial, tool_type); - g_hash_table_insert (seat_impl->tools, libinput_tool, tool); - } - } - - if (evdev_device->last_tool != tool) - { - evdev_device->last_tool = tool; - input_settings = seat_impl->input_settings; - meta_input_settings_notify_tool_change (input_settings, input_device, tool); - } -} - -static double * -translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event, - ClutterInputDeviceTool *tool) -{ - double *axes = g_new0 (double, CLUTTER_INPUT_AXIS_LAST); - struct libinput_tablet_tool *libinput_tool; - double value; - - libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event); - - value = libinput_event_tablet_tool_get_x (tablet_event); - axes[CLUTTER_INPUT_AXIS_X] = value; - value = libinput_event_tablet_tool_get_y (tablet_event); - axes[CLUTTER_INPUT_AXIS_Y] = value; - - if (libinput_tablet_tool_has_distance (libinput_tool)) - { - value = libinput_event_tablet_tool_get_distance (tablet_event); - axes[CLUTTER_INPUT_AXIS_DISTANCE] = value; - } - - if (libinput_tablet_tool_has_pressure (libinput_tool)) - { - value = libinput_event_tablet_tool_get_pressure (tablet_event); - value = meta_input_device_tool_native_translate_pressure_in_impl (tool, value); - axes[CLUTTER_INPUT_AXIS_PRESSURE] = value; - } - - if (libinput_tablet_tool_has_tilt (libinput_tool)) - { - value = libinput_event_tablet_tool_get_tilt_x (tablet_event); - axes[CLUTTER_INPUT_AXIS_XTILT] = value; - value = libinput_event_tablet_tool_get_tilt_y (tablet_event); - axes[CLUTTER_INPUT_AXIS_YTILT] = value; - } - - if (libinput_tablet_tool_has_rotation (libinput_tool)) - { - value = libinput_event_tablet_tool_get_rotation (tablet_event); - axes[CLUTTER_INPUT_AXIS_ROTATION] = value; - } - - if (libinput_tablet_tool_has_slider (libinput_tool)) - { - value = libinput_event_tablet_tool_get_slider_position (tablet_event); - axes[CLUTTER_INPUT_AXIS_SLIDER] = value; - } - - if (libinput_tablet_tool_has_wheel (libinput_tool)) - { - value = libinput_event_tablet_tool_get_wheel_delta (tablet_event); - axes[CLUTTER_INPUT_AXIS_WHEEL] = value; - } - - return axes; -} - -static void -notify_continuous_axis (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint64_t time_us, - ClutterScrollSource scroll_source, - struct libinput_event_pointer *axis_event) -{ - double dx = 0.0, dy = 0.0; - ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE; - - if (libinput_event_pointer_has_axis (axis_event, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) - { - dx = libinput_event_pointer_get_axis_value ( - axis_event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - - if (fabs (dx) < DBL_EPSILON) - finish_flags |= CLUTTER_SCROLL_FINISHED_HORIZONTAL; - } - if (libinput_event_pointer_has_axis (axis_event, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) - { - dy = libinput_event_pointer_get_axis_value ( - axis_event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - - if (fabs (dy) < DBL_EPSILON) - finish_flags |= CLUTTER_SCROLL_FINISHED_VERTICAL; - } - - meta_seat_impl_notify_scroll_continuous_in_impl (seat_impl, device, time_us, - dx, dy, - scroll_source, finish_flags); -} - -static void -notify_discrete_axis (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint64_t time_us, - ClutterScrollSource scroll_source, - struct libinput_event_pointer *axis_event) -{ - double discrete_dx = 0.0, discrete_dy = 0.0; - - if (libinput_event_pointer_has_axis (axis_event, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) - { - discrete_dx = libinput_event_pointer_get_axis_value_discrete ( - axis_event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - } - if (libinput_event_pointer_has_axis (axis_event, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) - { - discrete_dy = libinput_event_pointer_get_axis_value_discrete ( - axis_event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - } - - meta_seat_impl_notify_discrete_scroll_in_impl (seat_impl, device, - time_us, - discrete_dx, discrete_dy, - scroll_source); -} - -static void -process_tablet_axis (MetaSeatImpl *seat_impl, - struct libinput_event *event) -{ - struct libinput_device *libinput_device = libinput_event_get_device (event); - uint64_t time; - double x, y, dx, dy, *axes; - float stage_width, stage_height; - ClutterInputDevice *device; - struct libinput_event_tablet_tool *tablet_event = - libinput_event_get_tablet_tool_event (event); - MetaInputDeviceNative *evdev_device; - - device = libinput_device_get_user_data (libinput_device); - evdev_device = META_INPUT_DEVICE_NATIVE (device); - - axes = translate_tablet_axes (tablet_event, - evdev_device->last_tool); - - meta_viewport_info_get_extents (seat_impl->viewports, - &stage_width, &stage_height); - - time = libinput_event_tablet_tool_get_time_usec (tablet_event); - - if (meta_input_device_native_get_mapping_mode_in_impl (device) == META_INPUT_DEVICE_MAPPING_RELATIVE || - clutter_input_device_tool_get_tool_type (evdev_device->last_tool) == CLUTTER_INPUT_DEVICE_TOOL_MOUSE || - clutter_input_device_tool_get_tool_type (evdev_device->last_tool) == CLUTTER_INPUT_DEVICE_TOOL_LENS) - { - dx = libinput_event_tablet_tool_get_dx (tablet_event); - dy = libinput_event_tablet_tool_get_dy (tablet_event); - notify_relative_tool_motion_in_impl (device, time, dx, dy, axes); - } - else - { - x = libinput_event_tablet_tool_get_x_transformed (tablet_event, stage_width); - y = libinput_event_tablet_tool_get_y_transformed (tablet_event, stage_height); - notify_absolute_motion_in_impl (device, time, x, y, axes); - } -} - -static gboolean -process_device_event (MetaSeatImpl *seat_impl, - struct libinput_event *event) -{ - gboolean handled = TRUE; - struct libinput_device *libinput_device = libinput_event_get_device(event); - ClutterInputDevice *device; - MetaInputDeviceNative *device_native; - - switch (libinput_event_get_type (event)) - { - case LIBINPUT_EVENT_KEYBOARD_KEY: - { - uint32_t key, key_state, seat_key_count; - uint64_t time_us; - struct libinput_event_keyboard *key_event = - libinput_event_get_keyboard_event (event); - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_keyboard_get_time_usec (key_event); - key = libinput_event_keyboard_get_key (key_event); - key_state = libinput_event_keyboard_get_key_state (key_event) == - LIBINPUT_KEY_STATE_PRESSED; - seat_key_count = - libinput_event_keyboard_get_seat_key_count (key_event); - - /* Ignore key events that are not seat wide state changes. */ - if ((key_state == LIBINPUT_KEY_STATE_PRESSED && - seat_key_count != 1) || - (key_state == LIBINPUT_KEY_STATE_RELEASED && - seat_key_count != 0)) - { - meta_topic (META_DEBUG_INPUT, - "Dropping key-%s of key 0x%x because seat-wide " - "key count is %d", - key_state == LIBINPUT_KEY_STATE_PRESSED ? "press" : "release", - key, seat_key_count); - break; - } - - meta_seat_impl_notify_key_in_impl (seat_impl, - device, - time_us, key, key_state, TRUE); - - break; - } - - case LIBINPUT_EVENT_POINTER_MOTION: - { - struct libinput_event_pointer *pointer_event = - libinput_event_get_pointer_event (event); - uint64_t time_us; - double dx; - double dy; - double dx_unaccel; - double dy_unaccel; - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_pointer_get_time_usec (pointer_event); - dx = libinput_event_pointer_get_dx (pointer_event); - dy = libinput_event_pointer_get_dy (pointer_event); - dx_unaccel = libinput_event_pointer_get_dx_unaccelerated (pointer_event); - dy_unaccel = libinput_event_pointer_get_dy_unaccelerated (pointer_event); - - meta_seat_impl_notify_relative_motion_in_impl (seat_impl, - device, - time_us, - dx, dy, - dx_unaccel, dy_unaccel); - - break; - } - - case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - { - uint64_t time_us; - double x, y; - float stage_width, stage_height; - struct libinput_event_pointer *motion_event = - libinput_event_get_pointer_event (event); - device = libinput_device_get_user_data (libinput_device); - - meta_viewport_info_get_extents (seat_impl->viewports, - &stage_width, &stage_height); - - time_us = libinput_event_pointer_get_time_usec (motion_event); - x = libinput_event_pointer_get_absolute_x_transformed (motion_event, - stage_width); - y = libinput_event_pointer_get_absolute_y_transformed (motion_event, - stage_height); - - meta_seat_impl_notify_absolute_motion_in_impl (seat_impl, - device, - time_us, - x, y, - NULL); - - break; - } - - case LIBINPUT_EVENT_POINTER_BUTTON: - { - uint32_t button, button_state, seat_button_count; - uint64_t time_us; - struct libinput_event_pointer *button_event = - libinput_event_get_pointer_event (event); - device = libinput_device_get_user_data (libinput_device); - - time_us = libinput_event_pointer_get_time_usec (button_event); - button = libinput_event_pointer_get_button (button_event); - button_state = libinput_event_pointer_get_button_state (button_event) == - LIBINPUT_BUTTON_STATE_PRESSED; - seat_button_count = - libinput_event_pointer_get_seat_button_count (button_event); - - /* Ignore button events that are not seat wide state changes. */ - if ((button_state == LIBINPUT_BUTTON_STATE_PRESSED && - seat_button_count != 1) || - (button_state == LIBINPUT_BUTTON_STATE_RELEASED && - seat_button_count != 0)) - { - meta_topic (META_DEBUG_INPUT, - "Dropping button-%s of button 0x%x because seat-wide " - "button count is %d", - button_state == LIBINPUT_BUTTON_STATE_PRESSED ? "press" : "release", - button, seat_button_count); - break; - } - - meta_seat_impl_notify_button_in_impl (seat_impl, device, - time_us, button, button_state); - break; - } - - case LIBINPUT_EVENT_POINTER_AXIS: - { - uint64_t time_us; - enum libinput_pointer_axis_source source; - struct libinput_event_pointer *axis_event = - libinput_event_get_pointer_event (event); - ClutterScrollSource scroll_source; - - device = libinput_device_get_user_data (libinput_device); - - time_us = libinput_event_pointer_get_time_usec (axis_event); - source = libinput_event_pointer_get_axis_source (axis_event); - scroll_source = translate_scroll_source (source); - - /* libinput < 0.8 sent wheel click events with value 10. Since 0.8 - the value is the angle of the click in degrees. To keep - backwards-compat with existing clients, we just send multiples of - the click count. */ - - switch (scroll_source) - { - case CLUTTER_SCROLL_SOURCE_WHEEL: - notify_discrete_axis (seat_impl, device, time_us, scroll_source, - axis_event); - break; - case CLUTTER_SCROLL_SOURCE_FINGER: - case CLUTTER_SCROLL_SOURCE_CONTINUOUS: - case CLUTTER_SCROLL_SOURCE_UNKNOWN: - notify_continuous_axis (seat_impl, device, time_us, scroll_source, - axis_event); - break; - } - break; - } - - case LIBINPUT_EVENT_TOUCH_DOWN: - { - int seat_slot; - uint64_t time_us; - double x, y; - float stage_width, stage_height; - MetaTouchState *touch_state; - struct libinput_event_touch *touch_event = - libinput_event_get_touch_event (event); - - device = libinput_device_get_user_data (libinput_device); - device_native = META_INPUT_DEVICE_NATIVE (device); - - meta_viewport_info_get_extents (seat_impl->viewports, - &stage_width, &stage_height); - - seat_slot = libinput_event_touch_get_seat_slot (touch_event); - time_us = libinput_event_touch_get_time_usec (touch_event); - x = libinput_event_touch_get_x_transformed (touch_event, - stage_width); - y = libinput_event_touch_get_y_transformed (touch_event, - stage_height); - - g_rw_lock_writer_lock (&seat_impl->state_lock); - - touch_state = meta_seat_impl_acquire_touch_state_in_impl (seat_impl, seat_slot); - touch_state->coords.x = x; - touch_state->coords.y = y; - - g_rw_lock_writer_unlock (&seat_impl->state_lock); - - meta_seat_impl_notify_touch_event_in_impl (seat_impl, device, - CLUTTER_TOUCH_BEGIN, - time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - break; - } - - case LIBINPUT_EVENT_TOUCH_UP: - { - int seat_slot; - uint64_t time_us; - MetaTouchState *touch_state; - struct libinput_event_touch *touch_event = - libinput_event_get_touch_event (event); - - device = libinput_device_get_user_data (libinput_device); - device_native = META_INPUT_DEVICE_NATIVE (device); - - seat_slot = libinput_event_touch_get_seat_slot (touch_event); - time_us = libinput_event_touch_get_time_usec (touch_event); - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat_impl, seat_slot); - if (!touch_state) - break; - - meta_seat_impl_notify_touch_event_in_impl (seat_impl, device, - CLUTTER_TOUCH_END, time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - - g_rw_lock_writer_lock (&seat_impl->state_lock); - meta_seat_impl_release_touch_state_in_impl (seat_impl, seat_slot); - g_rw_lock_writer_unlock (&seat_impl->state_lock); - break; - } - - case LIBINPUT_EVENT_TOUCH_MOTION: - { - int seat_slot; - uint64_t time_us; - double x, y; - float stage_width, stage_height; - MetaTouchState *touch_state; - struct libinput_event_touch *touch_event = - libinput_event_get_touch_event (event); - - device = libinput_device_get_user_data (libinput_device); - device_native = META_INPUT_DEVICE_NATIVE (device); - - meta_viewport_info_get_extents (seat_impl->viewports, - &stage_width, &stage_height); - - seat_slot = libinput_event_touch_get_seat_slot (touch_event); - time_us = libinput_event_touch_get_time_usec (touch_event); - x = libinput_event_touch_get_x_transformed (touch_event, - stage_width); - y = libinput_event_touch_get_y_transformed (touch_event, - stage_height); - - g_rw_lock_writer_lock (&seat_impl->state_lock); - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat_impl, seat_slot); - if (touch_state) - { - touch_state->coords.x = x; - touch_state->coords.y = y; - } - g_rw_lock_writer_unlock (&seat_impl->state_lock); - - if (!touch_state) - break; - - meta_seat_impl_notify_touch_event_in_impl (seat_impl, device, - CLUTTER_TOUCH_UPDATE, - time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - break; - } - case LIBINPUT_EVENT_TOUCH_CANCEL: - { - int seat_slot; - MetaTouchState *touch_state; - uint64_t time_us; - struct libinput_event_touch *touch_event = - libinput_event_get_touch_event (event); - - device = libinput_device_get_user_data (libinput_device); - device_native = META_INPUT_DEVICE_NATIVE (device); - time_us = libinput_event_touch_get_time_usec (touch_event); - - seat_slot = libinput_event_touch_get_seat_slot (touch_event); - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat_impl, seat_slot); - if (!touch_state) - break; - - meta_seat_impl_notify_touch_event_in_impl (touch_state->seat_impl, - CLUTTER_INPUT_DEVICE (device_native), - CLUTTER_TOUCH_CANCEL, - time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - - meta_seat_impl_release_touch_state_in_impl (seat_impl, seat_slot); - break; - } - case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: - case LIBINPUT_EVENT_GESTURE_PINCH_END: - { - struct libinput_event_gesture *gesture_event = - libinput_event_get_gesture_event (event); - ClutterTouchpadGesturePhase phase; - uint32_t n_fingers; - uint64_t time_us; - - if (libinput_event_get_type (event) == LIBINPUT_EVENT_GESTURE_PINCH_BEGIN) - phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN; - else - phase = libinput_event_gesture_get_cancelled (gesture_event) ? - CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL : CLUTTER_TOUCHPAD_GESTURE_PHASE_END; - - n_fingers = libinput_event_gesture_get_finger_count (gesture_event); - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_gesture_get_time_usec (gesture_event); - notify_pinch_gesture_event (device, phase, time_us, 0, 0, 0, 0, 0, 0, n_fingers); - break; - } - case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: - { - struct libinput_event_gesture *gesture_event = - libinput_event_get_gesture_event (event); - double angle_delta, scale, dx, dy, dx_unaccel, dy_unaccel; - uint32_t n_fingers; - uint64_t time_us; - - n_fingers = libinput_event_gesture_get_finger_count (gesture_event); - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_gesture_get_time_usec (gesture_event); - angle_delta = libinput_event_gesture_get_angle_delta (gesture_event); - scale = libinput_event_gesture_get_scale (gesture_event); - dx = libinput_event_gesture_get_dx (gesture_event); - dy = libinput_event_gesture_get_dy (gesture_event); - dx_unaccel = libinput_event_gesture_get_dx_unaccelerated (gesture_event); - dy_unaccel = libinput_event_gesture_get_dy_unaccelerated (gesture_event); - - notify_pinch_gesture_event (device, - CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE, - time_us, dx, dy, dx_unaccel, dy_unaccel, - angle_delta, scale, n_fingers); - break; - } - case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: - case LIBINPUT_EVENT_GESTURE_SWIPE_END: - { - struct libinput_event_gesture *gesture_event = - libinput_event_get_gesture_event (event); - ClutterTouchpadGesturePhase phase; - uint32_t n_fingers; - uint64_t time_us; - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_gesture_get_time_usec (gesture_event); - n_fingers = libinput_event_gesture_get_finger_count (gesture_event); - - if (libinput_event_get_type (event) == LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN) - phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN; - else - phase = libinput_event_gesture_get_cancelled (gesture_event) ? - CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL : CLUTTER_TOUCHPAD_GESTURE_PHASE_END; - - notify_swipe_gesture_event (device, phase, time_us, n_fingers, 0, 0, 0, 0); - break; - } - case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: - { - struct libinput_event_gesture *gesture_event = - libinput_event_get_gesture_event (event); - uint32_t n_fingers; - uint64_t time_us; - double dx, dy, dx_unaccel, dy_unaccel; - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_gesture_get_time_usec (gesture_event); - n_fingers = libinput_event_gesture_get_finger_count (gesture_event); - dx = libinput_event_gesture_get_dx (gesture_event); - dy = libinput_event_gesture_get_dy (gesture_event); - dx_unaccel = libinput_event_gesture_get_dx_unaccelerated (gesture_event); - dy_unaccel = libinput_event_gesture_get_dy_unaccelerated (gesture_event); - - notify_swipe_gesture_event (device, - CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE, - time_us, n_fingers, dx, dy, dx_unaccel, dy_unaccel); - break; - } - case LIBINPUT_EVENT_TABLET_TOOL_AXIS: - { - process_tablet_axis (seat_impl, event); - break; - } - case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: - { - uint64_t time; - struct libinput_event_tablet_tool *tablet_event = - libinput_event_get_tablet_tool_event (event); - struct libinput_tablet_tool *libinput_tool = NULL; - enum libinput_tablet_tool_proximity_state state; - gboolean in; - - state = libinput_event_tablet_tool_get_proximity_state (tablet_event); - time = libinput_event_tablet_tool_get_time_usec (tablet_event); - device = libinput_device_get_user_data (libinput_device); - in = state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN; - - libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event); - - if (in) - input_device_update_tool (seat_impl, device, libinput_tool); - notify_proximity (device, time, in); - if (!in) - input_device_update_tool (seat_impl, device, NULL); - - break; - } - case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: - { - uint64_t time_us; - uint32_t button_state; - struct libinput_event_tablet_tool *tablet_event = - libinput_event_get_tablet_tool_event (event); - uint32_t tablet_button; - - process_tablet_axis (seat_impl, event); - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_tablet_tool_get_time_usec (tablet_event); - tablet_button = libinput_event_tablet_tool_get_button (tablet_event); - - button_state = libinput_event_tablet_tool_get_button_state (tablet_event) == - LIBINPUT_BUTTON_STATE_PRESSED; - - meta_seat_impl_notify_button_in_impl (seat_impl, device, - time_us, tablet_button, button_state); - break; - } - case LIBINPUT_EVENT_TABLET_TOOL_TIP: - { - uint64_t time_us; - uint32_t button_state; - struct libinput_event_tablet_tool *tablet_event = - libinput_event_get_tablet_tool_event (event); - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_tablet_tool_get_time_usec (tablet_event); - - button_state = libinput_event_tablet_tool_get_tip_state (tablet_event) == - LIBINPUT_TABLET_TOOL_TIP_DOWN; - - /* To avoid jumps on tip, notify axes before the tip down event - but after the tip up event */ - if (button_state) - process_tablet_axis (seat_impl, event); - - meta_seat_impl_notify_button_in_impl (seat_impl, device, - time_us, BTN_TOUCH, button_state); - if (!button_state) - process_tablet_axis (seat_impl, event); - break; - } - case LIBINPUT_EVENT_TABLET_PAD_BUTTON: - { - uint64_t time; - uint32_t button_state, button, group, mode; - struct libinput_tablet_pad_mode_group *mode_group; - struct libinput_event_tablet_pad *pad_event = - libinput_event_get_tablet_pad_event (event); - - device = libinput_device_get_user_data (libinput_device); - time = libinput_event_tablet_pad_get_time_usec (pad_event); - - mode_group = libinput_event_tablet_pad_get_mode_group (pad_event); - group = libinput_tablet_pad_mode_group_get_index (mode_group); - mode = libinput_event_tablet_pad_get_mode (pad_event); - - button = libinput_event_tablet_pad_get_button_number (pad_event); - button_state = libinput_event_tablet_pad_get_button_state (pad_event) == - LIBINPUT_BUTTON_STATE_PRESSED; - notify_pad_button (device, time, button, group, mode, button_state); - break; - } - case LIBINPUT_EVENT_TABLET_PAD_STRIP: - { - uint64_t time; - uint32_t number, source, group, mode; - struct libinput_tablet_pad_mode_group *mode_group; - struct libinput_event_tablet_pad *pad_event = - libinput_event_get_tablet_pad_event (event); - double value; - - device = libinput_device_get_user_data (libinput_device); - time = libinput_event_tablet_pad_get_time_usec (pad_event); - number = libinput_event_tablet_pad_get_strip_number (pad_event); - value = libinput_event_tablet_pad_get_strip_position (pad_event); - source = libinput_event_tablet_pad_get_strip_source (pad_event); - - mode_group = libinput_event_tablet_pad_get_mode_group (pad_event); - group = libinput_tablet_pad_mode_group_get_index (mode_group); - mode = libinput_event_tablet_pad_get_mode (pad_event); - - notify_pad_strip (device, time, number, source, group, mode, value); - break; - } - case LIBINPUT_EVENT_TABLET_PAD_RING: - { - uint64_t time; - uint32_t number, source, group, mode; - struct libinput_tablet_pad_mode_group *mode_group; - struct libinput_event_tablet_pad *pad_event = - libinput_event_get_tablet_pad_event (event); - double angle; - - device = libinput_device_get_user_data (libinput_device); - time = libinput_event_tablet_pad_get_time_usec (pad_event); - number = libinput_event_tablet_pad_get_ring_number (pad_event); - angle = libinput_event_tablet_pad_get_ring_position (pad_event); - source = libinput_event_tablet_pad_get_ring_source (pad_event); - - mode_group = libinput_event_tablet_pad_get_mode_group (pad_event); - group = libinput_tablet_pad_mode_group_get_index (mode_group); - mode = libinput_event_tablet_pad_get_mode (pad_event); - - notify_pad_ring (device, time, number, source, group, mode, angle); - break; - } - case LIBINPUT_EVENT_SWITCH_TOGGLE: - { - struct libinput_event_switch *switch_event = - libinput_event_get_switch_event (event); - enum libinput_switch sw = - libinput_event_switch_get_switch (switch_event); - enum libinput_switch_state state = - libinput_event_switch_get_switch_state (switch_event); - - if (sw == LIBINPUT_SWITCH_TABLET_MODE) - { - seat_impl->tablet_mode_switch_state = (state == LIBINPUT_SWITCH_STATE_ON); - update_touch_mode (seat_impl); - } - break; - } - default: - handled = FALSE; - } - - return handled; -} - -static void -process_event (MetaSeatImpl *seat_impl, - struct libinput_event *event) -{ - if (process_base_event (seat_impl, event)) - return; - if (process_device_event (seat_impl, event)) - return; -} - -static void -process_events (MetaSeatImpl *seat_impl) -{ - struct libinput_event *event; - - while ((event = libinput_get_event (seat_impl->libinput))) - { - process_event(seat_impl, event); - libinput_event_destroy(event); - } -} - -static int -open_restricted (const char *path, - int open_flags, - void *user_data) -{ - MetaSeatImpl *seat_impl = user_data; - MetaSeatImplPrivate *priv = meta_seat_impl_get_instance_private (seat_impl); - MetaBackend *backend = meta_seat_native_get_backend (seat_impl->seat_native); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - MetaDeviceFileFlags flags; - g_autoptr (GError) error = NULL; - MetaDeviceFile *device_file; - int fd; - - flags = META_DEVICE_FILE_FLAG_NONE; - if (!(open_flags & (O_RDWR | O_WRONLY))) - flags |= META_DEVICE_FILE_FLAG_READ_ONLY; - - if (!g_str_has_prefix (path, "/sys/")) - flags |= META_DEVICE_FILE_FLAG_TAKE_CONTROL; - - device_file = meta_device_pool_open (device_pool, path, flags, &error); - if (!device_file) - { - g_warning ("Could not open device %s: %s", path, error->message); - return -1; - } - - fd = meta_device_file_get_fd (device_file); - g_hash_table_insert (priv->device_files, GINT_TO_POINTER (fd), device_file); - - return fd; -} - -static void -close_restricted (int fd, - void *user_data) -{ - MetaSeatImpl *seat_impl = user_data; - MetaSeatImplPrivate *priv = meta_seat_impl_get_instance_private (seat_impl); - - g_hash_table_remove (priv->device_files, GINT_TO_POINTER (fd)); -} - -static const struct libinput_interface libinput_interface = { - open_restricted, - close_restricted -}; - -static void -kbd_a11y_changed_cb (MetaInputSettings *input_settings, - MetaKbdA11ySettings *a11y_settings, - MetaSeatImpl *seat_impl) -{ - MetaInputDeviceNative *keyboard; - - keyboard = META_INPUT_DEVICE_NATIVE (seat_impl->core_keyboard); - meta_input_device_native_apply_kbd_a11y_settings_in_impl (keyboard, a11y_settings); -} - -static void -meta_seat_impl_set_keyboard_numlock_in_impl (MetaSeatImpl *seat_impl, - gboolean numlock_state) -{ - xkb_mod_mask_t depressed_mods; - xkb_mod_mask_t latched_mods; - xkb_mod_mask_t locked_mods; - xkb_mod_mask_t group_mods; - xkb_mod_mask_t numlock; - struct xkb_keymap *xkb_keymap; - MetaKeymapNative *keymap; - - keymap = seat_impl->keymap; - xkb_keymap = meta_keymap_native_get_keyboard_map_in_impl (keymap); - - numlock = (1 << xkb_keymap_mod_get_index (xkb_keymap, "Mod2")); - - depressed_mods = - xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_DEPRESSED); - latched_mods = - xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_LATCHED); - locked_mods = - xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_LOCKED); - group_mods = - xkb_state_serialize_layout (seat_impl->xkb, XKB_STATE_LAYOUT_EFFECTIVE); - - if (numlock_state) - locked_mods |= numlock; - else - locked_mods &= ~numlock; - - xkb_state_update_mask (seat_impl->xkb, - depressed_mods, - latched_mods, - locked_mods, - 0, 0, - group_mods); - - meta_seat_impl_sync_leds_in_impl (seat_impl); - meta_keymap_native_update_in_impl (seat_impl->keymap, - seat_impl, - seat_impl->xkb); -} - -static gboolean -init_libinput (MetaSeatImpl *seat_impl, - GError **error) -{ - MetaEventSource *source; - struct udev *udev; - struct libinput *libinput; - - udev = udev_new (); - if (G_UNLIKELY (udev == NULL)) - { - g_warning ("Failed to create udev object"); - seat_impl->input_thread_initialized = TRUE; - return FALSE; - } - - libinput = libinput_udev_create_context (&libinput_interface, - seat_impl, udev); - udev_unref (udev); - - if (libinput == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to create the libinput object."); - return FALSE; - } - - if (libinput_udev_assign_seat (libinput, seat_impl->seat_id) == -1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to assign a seat to the libinput object."); - libinput_unref (seat_impl->libinput); - return FALSE; - } - - seat_impl->libinput = libinput; - source = meta_event_source_new (seat_impl); - seat_impl->event_source = source; - - return TRUE; -} - -static gpointer -input_thread (MetaSeatImpl *seat_impl) -{ - MetaSeatImplPrivate *priv = meta_seat_impl_get_instance_private (seat_impl); - struct xkb_keymap *xkb_keymap; - - g_main_context_push_thread_default (seat_impl->input_context); - - priv->device_files = - g_hash_table_new_full (NULL, NULL, - NULL, - (GDestroyNotify) meta_device_file_release); - - if (!(seat_impl->flags & META_SEAT_NATIVE_FLAG_NO_LIBINPUT)) - { - g_autoptr (GError) error = NULL; - - if (!init_libinput (seat_impl, &error)) - { - g_critical ("Failed to initialize seat: %s", error->message); - seat_impl->input_thread_initialized = TRUE; - return NULL; - } - } - - seat_impl->input_settings = meta_input_settings_native_new_in_impl (seat_impl); - g_signal_connect_object (seat_impl->input_settings, "kbd-a11y-changed", - G_CALLBACK (kbd_a11y_changed_cb), seat_impl, 0); - - seat_impl->keymap = g_object_new (META_TYPE_KEYMAP_NATIVE, NULL); - - xkb_keymap = meta_keymap_native_get_keyboard_map_in_impl (seat_impl->keymap); - - if (xkb_keymap) - { - seat_impl->xkb = xkb_state_new (xkb_keymap); - - seat_impl->caps_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_CAPS); - seat_impl->num_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_NUM); - seat_impl->scroll_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL); - } - - if (meta_input_settings_maybe_restore_numlock_state (seat_impl->input_settings)) - meta_seat_impl_set_keyboard_numlock_in_impl (seat_impl, TRUE); - - seat_impl->has_touchscreen = has_touchscreen (seat_impl); - seat_impl->has_tablet_switch = has_tablet_switch (seat_impl); - update_touch_mode (seat_impl); - - g_mutex_lock (&seat_impl->init_mutex); - seat_impl->input_thread_initialized = TRUE; - g_cond_signal (&seat_impl->init_cond); - g_mutex_unlock (&seat_impl->init_mutex); - - seat_impl->input_loop = g_main_loop_new (seat_impl->input_context, FALSE); - g_main_loop_run (seat_impl->input_loop); - g_main_loop_unref (seat_impl->input_loop); - - g_main_context_pop_thread_default (seat_impl->input_context); - - return NULL; -} - -static gboolean -meta_seat_impl_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaSeatImpl *seat_impl = META_SEAT_IMPL (initable); - - seat_impl->input_context = g_main_context_new (); - seat_impl->main_context = g_main_context_ref_thread_default (); - g_assert (seat_impl->main_context == g_main_context_default ()); - - seat_impl->input_thread = - g_thread_try_new ("Mutter Input Thread", - (GThreadFunc) input_thread, - initable, - error); - if (!seat_impl->input_thread) - return FALSE; - - /* Initialize thread synchronously */ - g_mutex_lock (&seat_impl->init_mutex); - while (!seat_impl->input_thread_initialized) - g_cond_wait (&seat_impl->init_cond, &seat_impl->init_mutex); - g_mutex_unlock (&seat_impl->init_mutex); - - return TRUE; -} - -static void -meta_seat_impl_constructed (GObject *object) -{ - MetaSeatImpl *seat_impl = META_SEAT_IMPL (object); - ClutterInputDevice *device; - - device = meta_input_device_native_new_virtual ( - seat_impl, CLUTTER_POINTER_DEVICE, - CLUTTER_INPUT_MODE_LOGICAL); - seat_impl->pointer_x = INITIAL_POINTER_X; - seat_impl->pointer_y = INITIAL_POINTER_Y; - meta_input_device_native_set_coords_in_impl (META_INPUT_DEVICE_NATIVE (device), - seat_impl->pointer_x, - seat_impl->pointer_y); - seat_impl->core_pointer = device; - - device = meta_input_device_native_new_virtual ( - seat_impl, CLUTTER_KEYBOARD_DEVICE, - CLUTTER_INPUT_MODE_LOGICAL); - seat_impl->core_keyboard = device; - - if (G_OBJECT_CLASS (meta_seat_impl_parent_class)->constructed) - G_OBJECT_CLASS (meta_seat_impl_parent_class)->constructed (object); -} - -static void -meta_seat_impl_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaSeatImpl *seat_impl = META_SEAT_IMPL (object); - - switch (prop_id) - { - case PROP_SEAT: - seat_impl->seat_native = g_value_get_object (value); - break; - case PROP_SEAT_ID: - seat_impl->seat_id = g_value_dup_string (value); - break; - case PROP_FLAGS: - seat_impl->flags = g_value_get_flags (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_seat_impl_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaSeatImpl *seat_impl = META_SEAT_IMPL (object); - - switch (prop_id) - { - case PROP_SEAT: - g_value_set_object (value, seat_impl->seat_native); - break; - case PROP_SEAT_ID: - g_value_set_string (value, seat_impl->seat_id); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static gboolean -destroy_in_impl (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - MetaSeatImplPrivate *priv = meta_seat_impl_get_instance_private (seat_impl); - gboolean numlock_active; - - g_slist_foreach (seat_impl->devices, - (GFunc) meta_input_device_native_detach_libinput_in_impl, - NULL); - g_slist_free_full (seat_impl->devices, g_object_unref); - seat_impl->devices = NULL; - - g_clear_pointer (&seat_impl->libinput, libinput_unref); - g_clear_pointer (&seat_impl->tools, g_hash_table_unref); - g_clear_pointer (&seat_impl->touch_states, g_hash_table_destroy); - g_clear_pointer (&seat_impl->event_source, meta_event_source_free); - - numlock_active = - xkb_state_mod_name_is_active (seat_impl->xkb, XKB_MOD_NAME_NUM, - XKB_STATE_MODS_LATCHED | - XKB_STATE_MODS_LOCKED); - meta_input_settings_maybe_save_numlock_state (seat_impl->input_settings, - numlock_active); - - g_clear_pointer (&seat_impl->xkb, xkb_state_unref); - - meta_seat_impl_clear_repeat_source (seat_impl); - - g_clear_pointer (&priv->device_files, g_hash_table_destroy); - - g_main_loop_quit (seat_impl->input_loop); - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -void -meta_seat_impl_destroy (MetaSeatImpl *seat_impl) -{ - if (seat_impl->libinput) - { - GTask *task; - - task = g_task_new (seat_impl, NULL, NULL, NULL); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) destroy_in_impl); - g_object_unref (task); - - g_thread_join (seat_impl->input_thread); - g_assert (!seat_impl->libinput); - } - - g_object_unref (seat_impl); -} - -static void -meta_seat_impl_finalize (GObject *object) -{ - MetaSeatImpl *seat_impl = META_SEAT_IMPL (object); - - g_assert (!seat_impl->libinput); - g_assert (!seat_impl->tools); - g_assert (!seat_impl->event_source); - - g_free (seat_impl->seat_id); - - g_rw_lock_clear (&seat_impl->state_lock); - - G_OBJECT_CLASS (meta_seat_impl_parent_class)->finalize (object); -} - -ClutterInputDevice * -meta_seat_impl_get_pointer (MetaSeatImpl *seat_impl) -{ - return seat_impl->core_pointer; -} - -ClutterInputDevice * -meta_seat_impl_get_keyboard (MetaSeatImpl *seat_impl) -{ - return seat_impl->core_keyboard; -} - -GSList * -meta_seat_impl_get_devices_in_impl (MetaSeatImpl *seat_impl) -{ - return g_slist_copy_deep (seat_impl->devices, - (GCopyFunc) g_object_ref, - NULL); -} - -MetaKeymapNative * -meta_seat_impl_get_keymap (MetaSeatImpl *seat_impl) -{ - return g_object_ref (seat_impl->keymap); -} - -static gboolean -warp_pointer_in_impl (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - graphene_point_t *point; - - point = g_task_get_task_data (task); - notify_absolute_motion_in_impl (seat_impl->core_pointer, 0, - point->x, point->y, NULL); - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -void -meta_seat_impl_warp_pointer (MetaSeatImpl *seat_impl, - int x, - int y) -{ - graphene_point_t *point; - GTask *task; - - point = graphene_point_alloc (); - point->x = x; - point->y = y; - - task = g_task_new (seat_impl, NULL, NULL, NULL); - g_task_set_task_data (task, point, (GDestroyNotify) graphene_point_free); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) warp_pointer_in_impl); - g_object_unref (task); -} - -gboolean -meta_seat_impl_query_state (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - ClutterEventSequence *sequence, - graphene_point_t *coords, - ClutterModifierType *modifiers) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - gboolean retval = FALSE; - ClutterModifierType mods = 0; - - g_rw_lock_reader_lock (&seat_impl->state_lock); - - if (sequence) - { - MetaTouchState *touch_state; - int slot; - - slot = clutter_event_sequence_get_slot (sequence); - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat_impl, slot); - if (!touch_state) - goto out; - - if (coords) - { - coords->x = touch_state->coords.x; - coords->y = touch_state->coords.y; - } - - if (seat_impl->xkb) - mods = meta_xkb_translate_modifiers (seat_impl->xkb, 0); - - retval = TRUE; - } - else - { - if (coords) - { - coords->x = device_native->pointer_x; - coords->y = device_native->pointer_y; - } - - if (seat_impl->xkb) - { - mods = meta_xkb_translate_modifiers (seat_impl->xkb, - seat_impl->button_state); - } - - retval = TRUE; - } - - if (modifiers) - *modifiers = mods; - - out: - g_rw_lock_reader_unlock (&seat_impl->state_lock); - return retval; -} - -static void -meta_seat_impl_initable_iface_init (GInitableIface *iface) -{ - iface->init = meta_seat_impl_initable_init; -} - -static void -meta_seat_impl_class_init (MetaSeatImplClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_seat_impl_constructed; - object_class->set_property = meta_seat_impl_set_property; - object_class->get_property = meta_seat_impl_get_property; - object_class->finalize = meta_seat_impl_finalize; - - props[PROP_SEAT] = - g_param_spec_object ("seat", - "Seat", - "Seat", - META_TYPE_SEAT_NATIVE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - props[PROP_SEAT_ID] = - g_param_spec_string ("seat-id", - "Seat ID", - "Seat ID", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - props[PROP_FLAGS] = - g_param_spec_flags ("flags", - "Flags", - "Flags", - META_TYPE_SEAT_NATIVE_FLAG, - META_SEAT_NATIVE_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - signals[KBD_A11Y_FLAGS_CHANGED] = - g_signal_new ("kbd-a11y-flags-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); - signals[KBD_A11Y_MODS_STATE_CHANGED] = - g_signal_new ("kbd-a11y-mods-state-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); - signals[TOUCH_MODE] = - g_signal_new ("touch-mode", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - signals[BELL] = - g_signal_new ("bell", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - signals[MODS_STATE_CHANGED] = - g_signal_new ("mods-state-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - - g_object_class_install_properties (object_class, N_PROPS, props); -} - -static void -meta_seat_impl_init (MetaSeatImpl *seat_impl) -{ - g_rw_lock_init (&seat_impl->state_lock); - - seat_impl->repeat = TRUE; - seat_impl->repeat_delay = 250; /* ms */ - seat_impl->repeat_interval = 33; /* ms */ - - g_mutex_init (&seat_impl->init_mutex); - g_cond_init (&seat_impl->init_cond); - - seat_impl->barrier_manager = meta_barrier_manager_native_new (); -} - -void -meta_seat_impl_update_xkb_state_in_impl (MetaSeatImpl *seat_impl) -{ - xkb_mod_mask_t latched_mods = 0; - xkb_mod_mask_t locked_mods = 0; - struct xkb_keymap *xkb_keymap; - - g_rw_lock_writer_lock (&seat_impl->state_lock); - - xkb_keymap = meta_keymap_native_get_keyboard_map_in_impl (seat_impl->keymap); - - if (seat_impl->xkb) - { - latched_mods = xkb_state_serialize_mods (seat_impl->xkb, - XKB_STATE_MODS_LATCHED); - locked_mods = xkb_state_serialize_mods (seat_impl->xkb, - XKB_STATE_MODS_LOCKED); - xkb_state_unref (seat_impl->xkb); - } - - seat_impl->xkb = xkb_state_new (xkb_keymap); - - xkb_state_update_mask (seat_impl->xkb, - 0, /* depressed */ - latched_mods, - locked_mods, - 0, 0, seat_impl->layout_idx); - - seat_impl->caps_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_CAPS); - seat_impl->num_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_NUM); - seat_impl->scroll_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL); - - meta_seat_impl_sync_leds_in_impl (seat_impl); - meta_keymap_native_update_in_impl (seat_impl->keymap, - seat_impl, - seat_impl->xkb); - - g_rw_lock_writer_unlock (&seat_impl->state_lock); -} - -static gboolean -release_devices (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - - if (seat_impl->released) - { - g_warning ("meta_seat_impl_release_devices() shouldn't be called " - "multiple times without a corresponding call to " - "meta_seat_impl_reclaim_devices() first"); - } - else - { - libinput_suspend (seat_impl->libinput); - process_events (seat_impl); - - seat_impl->released = TRUE; - } - - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -/** - * meta_seat_impl_release_devices: - * - * Releases all the evdev devices that Clutter is currently managing. This api - * is typically used when switching away from the Clutter application when - * switching tty. The devices can be reclaimed later with a call to - * meta_seat_impl_reclaim_devices(). - * - * This function should only be called after clutter has been initialized. - */ -void -meta_seat_impl_release_devices (MetaSeatImpl *seat_impl) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) release_devices); - g_object_unref (task); -} - -static gboolean -reclaim_devices (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - - if (seat_impl->released) - { - libinput_resume (seat_impl->libinput); - meta_seat_impl_update_xkb_state_in_impl (seat_impl); - process_events (seat_impl); - - seat_impl->released = FALSE; - } - else - { - g_warning ("Spurious call to meta_seat_impl_reclaim_devices() without " - "previous call to meta_seat_impl_release_devices"); - } - - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -/** - * meta_seat_impl_reclaim_devices: - * - * This causes Clutter to re-probe for evdev devices. This is must only be - * called after a corresponding call to meta_seat_impl_release_devices() - * was previously used to release all evdev devices. This API is typically - * used when a clutter application using evdev has regained focus due to - * switching ttys. - * - * This function should only be called after clutter has been initialized. - */ -void -meta_seat_impl_reclaim_devices (MetaSeatImpl *seat_impl) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - meta_seat_impl_run_input_task (seat_impl, task, (GSourceFunc) reclaim_devices); - g_object_unref (task); -} - -static gboolean -set_keyboard_map (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - struct xkb_keymap *xkb_keymap = g_task_get_task_data (task); - MetaKeymapNative *keymap; - - keymap = seat_impl->keymap; - meta_keymap_native_set_keyboard_map_in_impl (keymap, xkb_keymap); - - meta_seat_impl_update_xkb_state_in_impl (seat_impl); - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -/** - * meta_seat_impl_set_keyboard_map: (skip) - * @seat_impl: the #ClutterSeat created by the evdev backend - * @keymap: the new keymap - * - * Instructs @evdev to use the speficied keyboard map. This will cause - * the backend to drop the state and create a new one with the new - * map. To avoid state being lost, callers should ensure that no key - * is pressed when calling this function. - */ -void -meta_seat_impl_set_keyboard_map (MetaSeatImpl *seat_impl, - struct xkb_keymap *xkb_keymap) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - g_return_if_fail (xkb_keymap != NULL); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - g_task_set_task_data (task, - xkb_keymap_ref (xkb_keymap), - (GDestroyNotify) xkb_keymap_unref); - meta_seat_impl_run_input_task (seat_impl, task, (GSourceFunc) set_keyboard_map); - g_object_unref (task); -} - -static gboolean -set_keyboard_layout_index (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - xkb_layout_index_t idx = GPOINTER_TO_UINT (g_task_get_task_data (task)); - xkb_mod_mask_t depressed_mods; - xkb_mod_mask_t latched_mods; - xkb_mod_mask_t locked_mods; - struct xkb_state *state; - - g_rw_lock_writer_lock (&seat_impl->state_lock); - - state = seat_impl->xkb; - - depressed_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED); - latched_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED); - locked_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED); - - xkb_state_update_mask (state, depressed_mods, latched_mods, locked_mods, 0, 0, idx); - meta_keymap_native_update_in_impl (seat_impl->keymap, - seat_impl, - seat_impl->xkb); - - seat_impl->layout_idx = idx; - - g_rw_lock_writer_unlock (&seat_impl->state_lock); - - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -/** - * meta_seat_impl_set_keyboard_layout_index: (skip) - * @seat_impl: the #ClutterSeat created by the evdev backend - * @idx: the xkb layout index to set - * - * Sets the xkb layout index on the backend's #xkb_state . - */ -void -meta_seat_impl_set_keyboard_layout_index (MetaSeatImpl *seat_impl, - xkb_layout_index_t idx) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - g_task_set_task_data (task, GUINT_TO_POINTER (idx), NULL); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) set_keyboard_layout_index); - g_object_unref (task); -} - -/** - * meta_seat_impl_set_keyboard_repeat_in_impl: - * @seat_impl: the #ClutterSeat created by the evdev backend - * @repeat: whether to enable or disable keyboard repeat events - * @delay: the delay in ms between the hardware key press event and - * the first synthetic event - * @interval: the period in ms between consecutive synthetic key - * press events - * - * Enables or disables sythetic key press events, allowing for initial - * delay and interval period to be specified. - */ -void -meta_seat_impl_set_keyboard_repeat_in_impl (MetaSeatImpl *seat_impl, - gboolean repeat, - uint32_t delay, - uint32_t interval) -{ - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - seat_impl->repeat = repeat; - seat_impl->repeat_delay = delay; - seat_impl->repeat_interval = interval; -} - -struct xkb_state * -meta_seat_impl_get_xkb_state_in_impl (MetaSeatImpl *seat_impl) -{ - return seat_impl->xkb; -} - -MetaBarrierManagerNative * -meta_seat_impl_get_barrier_manager (MetaSeatImpl *seat_impl) -{ - return seat_impl->barrier_manager; -} - -static gboolean -set_pointer_constraint (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - MetaPointerConstraintImpl *constraint_impl = g_task_get_task_data (task); - - if (!g_set_object (&seat_impl->pointer_constraint, constraint_impl)) - return G_SOURCE_REMOVE; - - if (constraint_impl) - { - meta_pointer_constraint_impl_ensure_constrained (constraint_impl, - seat_impl->core_pointer); - } - - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -void -meta_seat_impl_set_pointer_constraint (MetaSeatImpl *seat_impl, - MetaPointerConstraintImpl *constraint_impl) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - if (constraint_impl) - g_task_set_task_data (task, g_object_ref (constraint_impl), g_object_unref); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) set_pointer_constraint); - g_object_unref (task); -} - -static gboolean -set_viewports (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - MetaViewportInfo *viewports = g_task_get_task_data (task); - - g_set_object (&seat_impl->viewports, viewports); - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -void -meta_seat_impl_set_viewports (MetaSeatImpl *seat_impl, - MetaViewportInfo *viewports) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - g_task_set_task_data (task, g_object_ref (viewports), g_object_unref); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) set_viewports); - g_object_unref (task); -} - -MetaSeatImpl * -meta_seat_impl_new (MetaSeatNative *seat_native, - const char *seat_id, - MetaSeatNativeFlag flags) -{ - return g_initable_new (META_TYPE_SEAT_IMPL, - NULL, NULL, - "seat", seat_native, - "seat-id", seat_id, - "flags", flags, - NULL); -} - -void -meta_seat_impl_notify_kbd_a11y_flags_changed_in_impl (MetaSeatImpl *seat_impl, - MetaKeyboardA11yFlags new_flags, - MetaKeyboardA11yFlags what_changed) -{ - MetaInputSettings *input_settings; - GValue values[] = { G_VALUE_INIT, G_VALUE_INIT }; - - input_settings = seat_impl->input_settings; - meta_input_settings_notify_kbd_a11y_change (input_settings, - new_flags, what_changed); - g_value_init (&values[0], G_TYPE_UINT); - g_value_set_uint (&values[0], new_flags); - g_value_init (&values[1], G_TYPE_UINT); - g_value_set_uint (&values[1], what_changed); - - emit_signal (seat_impl, signals[KBD_A11Y_FLAGS_CHANGED], - values, G_N_ELEMENTS (values)); -} - -void -meta_seat_impl_notify_kbd_a11y_mods_state_changed_in_impl (MetaSeatImpl *seat_impl, - xkb_mod_mask_t new_latched_mods, - xkb_mod_mask_t new_locked_mods) -{ - GValue values[] = { G_VALUE_INIT, G_VALUE_INIT }; - - g_value_init (&values[0], G_TYPE_UINT); - g_value_set_uint (&values[0], new_latched_mods); - g_value_init (&values[1], G_TYPE_UINT); - g_value_set_uint (&values[1], new_locked_mods); - - emit_signal (seat_impl, signals[KBD_A11Y_MODS_STATE_CHANGED], - values, G_N_ELEMENTS (values)); -} - -void -meta_seat_impl_notify_bell_in_impl (MetaSeatImpl *seat_impl) -{ - emit_signal (seat_impl, signals[BELL], NULL, 0); -} - -MetaInputSettings * -meta_seat_impl_get_input_settings (MetaSeatImpl *seat_impl) -{ - return seat_impl->input_settings; -} diff --git a/src/backends/native/meta-seat-impl.h b/src/backends/native/meta-seat-impl.h deleted file mode 100644 index d3e2ab860..000000000 --- a/src/backends/native/meta-seat-impl.h +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * Copyright (C) 2016 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Damien Lespiau <damien.lespiau@intel.com> - * Author: Jonas Ådahl <jadahl@gmail.com> - */ - -#ifndef META_SEAT_IMPL_H -#define META_SEAT_IMPL_H - -#ifndef META_INPUT_THREAD_H_INSIDE -#error "This header cannot be included directly. Use "backends/native/meta-input-thread.h"" -#endif /* META_INPUT_THREAD_H_INSIDE */ - -#include <gudev/gudev.h> -#include <libinput.h> -#include <linux/input-event-codes.h> - -#include "backends/meta-input-settings-private.h" -#include "backends/meta-viewport-info.h" -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-barrier-native.h" -#include "backends/native/meta-cursor-renderer-native.h" -#include "backends/native/meta-keymap-native.h" -#include "backends/native/meta-pointer-constraint-native.h" -#include "backends/native/meta-xkb-utils.h" -#include "clutter/clutter.h" - -typedef struct _MetaTouchState MetaTouchState; -typedef struct _MetaSeatImpl MetaSeatImpl; -typedef struct _MetaEventSource MetaEventSource; - -struct _MetaTouchState -{ - MetaSeatImpl *seat_impl; - - int device_slot; - int seat_slot; - graphene_point_t coords; -}; - -struct _MetaSeatImpl -{ - GObject parent_instance; - - GMainContext *main_context; - GMainContext *input_context; - GMainLoop *input_loop; - GThread *input_thread; - GMutex init_mutex; - GCond init_cond; - - MetaSeatNative *seat_native; - char *seat_id; - MetaSeatNativeFlag flags; - MetaEventSource *event_source; - struct libinput *libinput; - GRWLock state_lock; - - GSList *devices; - GHashTable *tools; - - ClutterInputDevice *core_pointer; - ClutterInputDevice *core_keyboard; - - GHashTable *touch_states; - GHashTable *cursor_renderers; - - struct xkb_state *xkb; - xkb_led_index_t caps_lock_led; - xkb_led_index_t num_lock_led; - xkb_led_index_t scroll_lock_led; - xkb_layout_index_t layout_idx; - uint32_t button_state; - int button_count[KEY_CNT]; - - MetaBarrierManagerNative *barrier_manager; - MetaPointerConstraintImpl *pointer_constraint; - - MetaKeymapNative *keymap; - MetaInputSettings *input_settings; - - MetaViewportInfo *viewports; - - gboolean tablet_mode_switch_state; - gboolean has_touchscreen; - gboolean has_tablet_switch; - gboolean has_pointer; - gboolean touch_mode; - gboolean input_thread_initialized; - - /* keyboard repeat */ - gboolean repeat; - uint32_t repeat_delay; - uint32_t repeat_interval; - uint32_t repeat_key; - uint32_t repeat_count; - ClutterInputDevice *repeat_device; - GSource *repeat_source; - - float pointer_x; - float pointer_y; - - /* Emulation of discrete scroll events out of smooth ones */ - float accum_scroll_dx; - float accum_scroll_dy; - - gboolean released; -}; - -#define META_TYPE_SEAT_IMPL meta_seat_impl_get_type () -G_DECLARE_FINAL_TYPE (MetaSeatImpl, meta_seat_impl, - META, SEAT_IMPL, GObject) - -MetaSeatImpl * meta_seat_impl_new (MetaSeatNative *seat_native, - const char *seat_id, - MetaSeatNativeFlag flags); - -void meta_seat_impl_destroy (MetaSeatImpl *seat_impl); - -void meta_seat_impl_run_input_task (MetaSeatImpl *seat_impl, - GTask *task, - GSourceFunc dispatch_func); - -void meta_seat_impl_notify_key_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint64_t time_us, - uint32_t key, - uint32_t state, - gboolean update_keys); - -void meta_seat_impl_notify_relative_motion_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - float dx, - float dy, - float dx_unaccel, - float dy_unaccel); - -void meta_seat_impl_notify_absolute_motion_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - float x, - float y, - double *axes); - -void meta_seat_impl_notify_button_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - uint32_t button, - uint32_t state); - -void meta_seat_impl_notify_scroll_continuous_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - double dx, - double dy, - ClutterScrollSource source, - ClutterScrollFinishFlags flags); - -void meta_seat_impl_notify_discrete_scroll_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - double discrete_dx, - double discrete_dy, - ClutterScrollSource source); - -void meta_seat_impl_notify_touch_event_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - ClutterEventType evtype, - uint64_t time_us, - int slot, - double x, - double y); - -void meta_seat_impl_sync_leds_in_impl (MetaSeatImpl *seat_impl); - -MetaTouchState * meta_seat_impl_acquire_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot); -MetaTouchState * meta_seat_impl_lookup_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot); -void meta_seat_impl_release_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot); - -void meta_seat_impl_update_xkb_state_in_impl (MetaSeatImpl *seat_impl); - -void meta_seat_impl_release_devices (MetaSeatImpl *seat_impl); -void meta_seat_impl_reclaim_devices (MetaSeatImpl *seat_impl); - -struct xkb_state * meta_seat_impl_get_xkb_state_in_impl (MetaSeatImpl *seat_impl); - -void meta_seat_impl_set_keyboard_map (MetaSeatImpl *seat_impl, - struct xkb_keymap *keymap); - -void meta_seat_impl_set_keyboard_layout_index (MetaSeatImpl *seat_impl, - xkb_layout_index_t idx); - -void meta_seat_impl_set_keyboard_repeat_in_impl (MetaSeatImpl *seat_impl, - gboolean repeat, - uint32_t delay, - uint32_t interval); - -MetaBarrierManagerNative * meta_seat_impl_get_barrier_manager (MetaSeatImpl *seat_impl); - -void meta_seat_impl_set_pointer_constraint (MetaSeatImpl *seat_impl, - MetaPointerConstraintImpl *constraint_impl); -void meta_seat_impl_set_viewports (MetaSeatImpl *seat_impl, - MetaViewportInfo *viewports); - -void meta_seat_impl_warp_pointer (MetaSeatImpl *seat_impl, - int x, - int y); -gboolean meta_seat_impl_query_state (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - ClutterEventSequence *sequence, - graphene_point_t *coords, - ClutterModifierType *modifiers); -ClutterInputDevice * meta_seat_impl_get_pointer (MetaSeatImpl *seat_impl); -ClutterInputDevice * meta_seat_impl_get_keyboard (MetaSeatImpl *seat_impl); -GSList * meta_seat_impl_get_devices_in_impl (MetaSeatImpl *seat_impl); - -MetaKeymapNative * meta_seat_impl_get_keymap (MetaSeatImpl *seat_impl); - -void meta_seat_impl_notify_kbd_a11y_flags_changed_in_impl (MetaSeatImpl *seat_impl, - MetaKeyboardA11yFlags new_flags, - MetaKeyboardA11yFlags what_changed); -void meta_seat_impl_notify_kbd_a11y_mods_state_changed_in_impl (MetaSeatImpl *seat_impl, - xkb_mod_mask_t new_latched_mods, - xkb_mod_mask_t new_locked_mods); -void meta_seat_impl_notify_bell_in_impl (MetaSeatImpl *seat_impl); - -MetaInputSettings * meta_seat_impl_get_input_settings (MetaSeatImpl *seat_impl); - -void meta_seat_impl_queue_main_thread_idle (MetaSeatImpl *seat_impl, - GSourceFunc func, - gpointer user_data, - GDestroyNotify destroy_notify); - -#endif /* META_SEAT_IMPL_H */ diff --git a/src/backends/native/meta-seat-native.c b/src/backends/native/meta-seat-native.c deleted file mode 100644 index 12fead1fb..000000000 --- a/src/backends/native/meta-seat-native.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * Copyright (C) 2016 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Damien Lespiau <damien.lespiau@intel.com> - * Author: Jonas Ådahl <jadahl@gmail.com> - */ - -#include "config.h" - -#include "backends/native/meta-seat-native.h" - -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-keymap-utils.h" -#include "backends/native/meta-barrier-native.h" -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-keymap-native.h" -#include "backends/native/meta-virtual-input-device-native.h" -#include "clutter/clutter-mutter.h" -#include "core/bell.h" - -#include "meta-private-enum-types.h" - -enum -{ - PROP_0, - PROP_SEAT_ID, - PROP_FLAGS, - PROP_BACKEND, - N_PROPS, - - /* This property is overridden */ - PROP_TOUCH_MODE, -}; - -static GParamSpec *props[N_PROPS] = { NULL }; - -G_DEFINE_TYPE (MetaSeatNative, meta_seat_native, CLUTTER_TYPE_SEAT) - -static gboolean -meta_seat_native_handle_event_post (ClutterSeat *seat, - const ClutterEvent *event) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - ClutterInputDevice *device = clutter_event_get_source_device (event); - ClutterEventType event_type = event->type; - - if (event_type == CLUTTER_PROXIMITY_IN) - { - MetaCursorRenderer *cursor_renderer; - - if (!seat_native->tablet_cursors) - { - seat_native->tablet_cursors = g_hash_table_new_full (NULL, NULL, NULL, - g_object_unref); - } - - cursor_renderer = meta_cursor_renderer_new (meta_get_backend (), device); - g_hash_table_insert (seat_native->tablet_cursors, - device, cursor_renderer); - return TRUE; - } - else if (event_type == CLUTTER_PROXIMITY_OUT) - { - if (seat_native->tablet_cursors) - g_hash_table_remove (seat_native->tablet_cursors, device); - return TRUE; - } - else if (event_type == CLUTTER_DEVICE_ADDED) - { - if (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_LOGICAL) - seat_native->devices = g_list_prepend (seat_native->devices, g_object_ref (device)); - } - else if (event_type == CLUTTER_DEVICE_REMOVED) - { - GList *l = g_list_find (seat_native->devices, device); - - if (l) - { - seat_native->devices = g_list_delete_link (seat_native->devices, l); - g_object_unref (device); - } - } - - return FALSE; -} - -static void -proxy_kbd_a11y_flags_changed (MetaSeatImpl *seat_impl, - MetaKeyboardA11yFlags new_flags, - MetaKeyboardA11yFlags what_changed, - MetaSeatNative *seat_native) -{ - g_signal_emit_by_name (seat_native, - "kbd-a11y-flags-changed", - new_flags, what_changed); -} - -static void -proxy_kbd_a11y_mods_state_changed (MetaSeatImpl *seat_impl, - xkb_mod_mask_t new_latched_mods, - xkb_mod_mask_t new_locked_mods, - MetaSeatNative *seat_native) -{ - g_signal_emit_by_name (seat_native, - "kbd-a11y-mods-state-changed", - new_latched_mods, - new_locked_mods); -} - -static void -proxy_touch_mode_changed (MetaSeatImpl *seat_impl, - gboolean enabled, - MetaSeatNative *seat_native) -{ - seat_native->touch_mode = enabled; - g_object_notify (G_OBJECT (seat_native), "touch-mode"); -} - -static void -proxy_bell (MetaSeatImpl *seat_impl, - MetaSeatNative *seat_native) -{ - clutter_seat_bell_notify (CLUTTER_SEAT (seat_native)); -} - -static void -proxy_mods_state_changed (MetaSeatImpl *seat_impl, - ClutterSeat *seat) -{ - ClutterKeymap *keymap; - - keymap = clutter_seat_get_keymap (seat); - g_signal_emit_by_name (keymap, "state-changed"); -} - -static void -meta_seat_native_constructed (GObject *object) -{ - MetaSeatNative *seat = META_SEAT_NATIVE (object); - - seat->impl = meta_seat_impl_new (seat, seat->seat_id, seat->flags); - g_signal_connect (seat->impl, "kbd-a11y-flags-changed", - G_CALLBACK (proxy_kbd_a11y_flags_changed), seat); - g_signal_connect (seat->impl, "kbd-a11y-mods-state-changed", - G_CALLBACK (proxy_kbd_a11y_mods_state_changed), seat); - g_signal_connect (seat->impl, "touch-mode", - G_CALLBACK (proxy_touch_mode_changed), seat); - g_signal_connect (seat->impl, "bell", - G_CALLBACK (proxy_bell), seat); - g_signal_connect (seat->impl, "mods-state-changed", - G_CALLBACK (proxy_mods_state_changed), seat); - - seat->core_pointer = meta_seat_impl_get_pointer (seat->impl); - seat->core_keyboard = meta_seat_impl_get_keyboard (seat->impl); - - meta_seat_native_set_keyboard_map (seat, "us", "", ""); - - if (G_OBJECT_CLASS (meta_seat_native_parent_class)->constructed) - G_OBJECT_CLASS (meta_seat_native_parent_class)->constructed (object); -} - -static void -meta_seat_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT_ID: - seat_native->seat_id = g_value_dup_string (value); - break; - case PROP_FLAGS: - seat_native->flags = g_value_get_flags (value); - break; - case PROP_BACKEND: - seat_native->backend = g_value_get_object (value); - break; - case PROP_TOUCH_MODE: - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_seat_native_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT_ID: - g_value_set_string (value, seat_native->seat_id); - break; - case PROP_TOUCH_MODE: - g_value_set_boolean (value, seat_native->touch_mode); - break; - case PROP_FLAGS: - g_value_set_flags (value, seat_native->flags); - break; - case PROP_BACKEND: - g_value_set_object (value, seat_native->backend); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_seat_native_dispose (GObject *object) -{ - MetaSeatNative *seat = META_SEAT_NATIVE (object); - - g_clear_pointer (&seat->xkb_keymap, xkb_keymap_unref); - g_clear_object (&seat->core_pointer); - g_clear_object (&seat->core_keyboard); - g_clear_pointer (&seat->impl, meta_seat_impl_destroy); - g_list_free_full (g_steal_pointer (&seat->devices), g_object_unref); - g_clear_pointer (&seat->reserved_virtual_slots, g_hash_table_destroy); - g_clear_pointer (&seat->tablet_cursors, g_hash_table_unref); - g_clear_object (&seat->cursor_renderer); - - g_clear_pointer (&seat->seat_id, g_free); - - G_OBJECT_CLASS (meta_seat_native_parent_class)->dispose (object); -} - -static ClutterInputDevice * -meta_seat_native_get_pointer (ClutterSeat *seat) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - return seat_native->core_pointer; -} - -static ClutterInputDevice * -meta_seat_native_get_keyboard (ClutterSeat *seat) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - return seat_native->core_keyboard; -} - -static const GList * -meta_seat_native_peek_devices (ClutterSeat *seat) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - return (const GList *) seat_native->devices; -} - -static void -meta_seat_native_bell_notify (ClutterSeat *seat) -{ - MetaDisplay *display = meta_get_display (); - - meta_bell_notify (display, NULL); -} - -static ClutterKeymap * -meta_seat_native_get_keymap (ClutterSeat *seat) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - if (!seat_native->keymap) - seat_native->keymap = meta_seat_impl_get_keymap (seat_native->impl); - - return CLUTTER_KEYMAP (seat_native->keymap); -} - -static guint -bump_virtual_touch_slot_base (MetaSeatNative *seat_native) -{ - while (TRUE) - { - if (seat_native->virtual_touch_slot_base < 0x100) - seat_native->virtual_touch_slot_base = 0x100; - - seat_native->virtual_touch_slot_base += - CLUTTER_VIRTUAL_INPUT_DEVICE_MAX_TOUCH_SLOTS; - - if (!g_hash_table_lookup (seat_native->reserved_virtual_slots, - GUINT_TO_POINTER (seat_native->virtual_touch_slot_base))) - break; - } - - return seat_native->virtual_touch_slot_base; -} - -static ClutterVirtualInputDevice * -meta_seat_native_create_virtual_device (ClutterSeat *seat, - ClutterInputDeviceType device_type) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - guint slot_base; - - slot_base = bump_virtual_touch_slot_base (seat_native); - g_hash_table_add (seat_native->reserved_virtual_slots, - GUINT_TO_POINTER (slot_base)); - - return g_object_new (META_TYPE_VIRTUAL_INPUT_DEVICE_NATIVE, - "seat", seat, - "slot-base", slot_base, - "device-type", device_type, - NULL); -} - -void -meta_seat_native_release_touch_slots (MetaSeatNative *seat, - guint base_slot) -{ - g_hash_table_remove (seat->reserved_virtual_slots, - GUINT_TO_POINTER (base_slot)); -} - -static ClutterVirtualDeviceType -meta_seat_native_get_supported_virtual_device_types (ClutterSeat *seat) -{ - return (CLUTTER_VIRTUAL_DEVICE_TYPE_KEYBOARD | - CLUTTER_VIRTUAL_DEVICE_TYPE_POINTER | - CLUTTER_VIRTUAL_DEVICE_TYPE_TOUCHSCREEN); -} - -static void -meta_seat_native_warp_pointer (ClutterSeat *seat, - int x, - int y) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - meta_seat_impl_warp_pointer (seat_native->impl, x, y); -} - -static gboolean -meta_seat_native_query_state (ClutterSeat *seat, - ClutterInputDevice *device, - ClutterEventSequence *sequence, - graphene_point_t *coords, - ClutterModifierType *modifiers) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - return meta_seat_impl_query_state (seat_native->impl, device, sequence, - coords, modifiers); -} - -static void -meta_seat_native_class_init (MetaSeatNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterSeatClass *seat_class = CLUTTER_SEAT_CLASS (klass); - - object_class->constructed = meta_seat_native_constructed; - object_class->set_property = meta_seat_native_set_property; - object_class->get_property = meta_seat_native_get_property; - object_class->dispose = meta_seat_native_dispose; - - seat_class->get_pointer = meta_seat_native_get_pointer; - seat_class->get_keyboard = meta_seat_native_get_keyboard; - seat_class->peek_devices = meta_seat_native_peek_devices; - seat_class->bell_notify = meta_seat_native_bell_notify; - seat_class->get_keymap = meta_seat_native_get_keymap; - seat_class->create_virtual_device = meta_seat_native_create_virtual_device; - seat_class->get_supported_virtual_device_types = meta_seat_native_get_supported_virtual_device_types; - seat_class->warp_pointer = meta_seat_native_warp_pointer; - seat_class->handle_event_post = meta_seat_native_handle_event_post; - seat_class->query_state = meta_seat_native_query_state; - - props[PROP_SEAT_ID] = - g_param_spec_string ("seat-id", - "Seat ID", - "Seat ID", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - props[PROP_FLAGS] = - g_param_spec_flags ("flags", - "Flags", - "Flags", - META_TYPE_SEAT_NATIVE_FLAG, - META_SEAT_NATIVE_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - props[PROP_BACKEND] = - g_param_spec_object ("backend", - "Backend", - "Backend", - META_TYPE_BACKEND, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, N_PROPS, props); - - g_object_class_override_property (object_class, PROP_TOUCH_MODE, - "touch-mode"); -} - -static void -meta_seat_native_init (MetaSeatNative *seat) -{ - seat->reserved_virtual_slots = g_hash_table_new (NULL, NULL); -} - -/** - * meta_seat_native_release_devices: - * - * Releases all the evdev devices that Clutter is currently managing. This api - * is typically used when switching away from the Clutter application when - * switching tty. The devices can be reclaimed later with a call to - * meta_seat_native_reclaim_devices(). - * - * This function should only be called after clutter has been initialized. - */ -void -meta_seat_native_release_devices (MetaSeatNative *seat) -{ - g_return_if_fail (META_IS_SEAT_NATIVE (seat)); - - if (seat->released) - { - g_warning ("meta_seat_native_release_devices() shouldn't be called " - "multiple times without a corresponding call to " - "meta_seat_native_reclaim_devices() first"); - return; - } - - meta_seat_impl_release_devices (seat->impl); - seat->released = TRUE; -} - -/** - * meta_seat_native_reclaim_devices: - * - * This causes Clutter to re-probe for evdev devices. This is must only be - * called after a corresponding call to meta_seat_native_release_devices() - * was previously used to release all evdev devices. This API is typically - * used when a clutter application using evdev has regained focus due to - * switching ttys. - * - * This function should only be called after clutter has been initialized. - */ -void -meta_seat_native_reclaim_devices (MetaSeatNative *seat) -{ - if (!seat->released) - { - g_warning ("Spurious call to meta_seat_native_reclaim_devices() without " - "previous call to meta_seat_native_release_devices"); - return; - } - - meta_seat_impl_reclaim_devices (seat->impl); - seat->released = FALSE; -} - -static struct xkb_keymap * -create_keymap (const char *layouts, - const char *variants, - const char *options) -{ - struct xkb_rule_names names; - struct xkb_keymap *keymap; - struct xkb_context *context; - - names.rules = DEFAULT_XKB_RULES_FILE; - names.model = DEFAULT_XKB_MODEL; - names.layout = layouts; - names.variant = variants; - names.options = options; - - context = meta_create_xkb_context (); - keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS); - xkb_context_unref (context); - - return keymap; -} - -/** - * meta_seat_native_set_keyboard_map: (skip) - * @seat: the #ClutterSeat created by the evdev backend - * @keymap: the new keymap - * - * Instructs @evdev to use the specified keyboard map. This will cause - * the backend to drop the state and create a new one with the new - * map. To avoid state being lost, callers should ensure that no key - * is pressed when calling this function. - */ -void -meta_seat_native_set_keyboard_map (MetaSeatNative *seat, - const char *layouts, - const char *variants, - const char *options) -{ - struct xkb_keymap *keymap, *impl_keymap; - - keymap = create_keymap (layouts, variants, options); - impl_keymap = create_keymap (layouts, variants, options); - - if (keymap == NULL) - { - g_warning ("Unable to load configured keymap: rules=%s, model=%s, layout=%s, variant=%s, options=%s", - DEFAULT_XKB_RULES_FILE, DEFAULT_XKB_MODEL, layouts, - variants, options); - return; - } - - if (seat->xkb_keymap) - xkb_keymap_unref (seat->xkb_keymap); - seat->xkb_keymap = keymap; - - meta_seat_impl_set_keyboard_map (seat->impl, impl_keymap); - xkb_keymap_unref (impl_keymap); -} - -/** - * meta_seat_native_get_keyboard_map: (skip) - * @seat: the #ClutterSeat created by the evdev backend - * - * Retrieves the #xkb_keymap in use by the evdev backend. - * - * Return value: the #xkb_keymap. - */ -struct xkb_keymap * -meta_seat_native_get_keyboard_map (MetaSeatNative *seat) -{ - g_return_val_if_fail (META_IS_SEAT_NATIVE (seat), NULL); - - return seat->xkb_keymap; -} - -/** - * meta_seat_native_set_keyboard_layout_index: (skip) - * @seat: the #ClutterSeat created by the evdev backend - * @idx: the xkb layout index to set - * - * Sets the xkb layout index on the backend's #xkb_state . - */ -void -meta_seat_native_set_keyboard_layout_index (MetaSeatNative *seat, - xkb_layout_index_t idx) -{ - g_return_if_fail (META_IS_SEAT_NATIVE (seat)); - - seat->xkb_layout_index = idx; - meta_seat_impl_set_keyboard_layout_index (seat->impl, idx); -} - -/** - * meta_seat_native_get_keyboard_layout_index: (skip) - */ -xkb_layout_index_t -meta_seat_native_get_keyboard_layout_index (MetaSeatNative *seat) -{ - return seat->xkb_layout_index; -} - -MetaBarrierManagerNative * -meta_seat_native_get_barrier_manager (MetaSeatNative *seat) -{ - return meta_seat_impl_get_barrier_manager (seat->impl); -} - -MetaBackend * -meta_seat_native_get_backend (MetaSeatNative *seat_native) -{ - return seat_native->backend; -} - -void -meta_seat_native_set_pointer_constraint (MetaSeatNative *seat, - MetaPointerConstraintImpl *constraint_impl) -{ - meta_seat_impl_set_pointer_constraint (seat->impl, constraint_impl); -} - -MetaCursorRenderer * -meta_seat_native_maybe_ensure_cursor_renderer (MetaSeatNative *seat_native, - ClutterInputDevice *device) -{ - if (device == seat_native->core_pointer) - { - if (!seat_native->cursor_renderer) - { - MetaCursorRendererNative *cursor_renderer_native; - - cursor_renderer_native = - meta_cursor_renderer_native_new (meta_get_backend (), - seat_native->core_pointer); - seat_native->cursor_renderer = - META_CURSOR_RENDERER (cursor_renderer_native); - } - - return seat_native->cursor_renderer; - } - - if (seat_native->tablet_cursors && - clutter_input_device_get_device_type (device) == CLUTTER_TABLET_DEVICE) - return g_hash_table_lookup (seat_native->tablet_cursors, device); - - return NULL; -} - -void -meta_seat_native_set_viewports (MetaSeatNative *seat, - MetaViewportInfo *viewports) -{ - meta_seat_impl_set_viewports (seat->impl, viewports); -} diff --git a/src/backends/native/meta-seat-native.h b/src/backends/native/meta-seat-native.h deleted file mode 100644 index 53ba00f51..000000000 --- a/src/backends/native/meta-seat-native.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * Copyright (C) 2016 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Damien Lespiau <damien.lespiau@intel.com> - * Author: Jonas Ådahl <jadahl@gmail.com> - */ - -#ifndef META_SEAT_NATIVE_H -#define META_SEAT_NATIVE_H - -#include <gudev/gudev.h> -#include <libinput.h> -#include <linux/input-event-codes.h> - -#include "backends/meta-input-settings-private.h" -#include "backends/meta-viewport-info.h" -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-barrier-native.h" -#include "backends/native/meta-cursor-renderer-native.h" -#include "backends/native/meta-pointer-constraint-native.h" -#include "backends/native/meta-xkb-utils.h" -#include "clutter/clutter.h" - -typedef struct _MetaSeatNative MetaSeatNative; - -struct _MetaSeatNative -{ - ClutterSeat parent_instance; - - MetaBackend *backend; - - MetaSeatImpl *impl; - char *seat_id; - MetaSeatNativeFlag flags; - - GList *devices; - struct xkb_keymap *xkb_keymap; - xkb_layout_index_t xkb_layout_index; - - ClutterInputDevice *core_pointer; - ClutterInputDevice *core_keyboard; - - guint virtual_touch_slot_base; - GHashTable *reserved_virtual_slots; - - MetaKeymapNative *keymap; - MetaCursorRenderer *cursor_renderer; - GHashTable *tablet_cursors; - - gboolean released; - gboolean touch_mode; -}; - -#define META_TYPE_SEAT_NATIVE meta_seat_native_get_type () -G_DECLARE_FINAL_TYPE (MetaSeatNative, meta_seat_native, - META, SEAT_NATIVE, ClutterSeat) - -void meta_seat_native_set_libinput_seat (MetaSeatNative *seat, - struct libinput_seat *libinput_seat); - -void meta_seat_native_sync_leds (MetaSeatNative *seat); - -/** - * MetaOpenDeviceCallback: - * @path: the device path - * @flags: flags to be passed to open - * - * This callback will be called when Clutter needs to access an input - * device. It should return an open file descriptor for the file at @path, - * or -1 if opening failed. - */ -typedef int (* MetaOpenDeviceCallback) (const char *path, - int flags, - gpointer user_data, - GError **error); -typedef void (* MetaCloseDeviceCallback) (int fd, - gpointer user_data); - -void meta_seat_native_set_device_callbacks (MetaOpenDeviceCallback open_callback, - MetaCloseDeviceCallback close_callback, - gpointer user_data); - -void meta_seat_native_release_devices (MetaSeatNative *seat); -void meta_seat_native_reclaim_devices (MetaSeatNative *seat); - -void meta_seat_native_set_keyboard_map (MetaSeatNative *seat, - const char *layouts, - const char *variants, - const char *options); - -struct xkb_keymap * meta_seat_native_get_keyboard_map (MetaSeatNative *seat); - -void meta_seat_native_set_keyboard_layout_index (MetaSeatNative *seat, - xkb_layout_index_t idx); - -xkb_layout_index_t meta_seat_native_get_keyboard_layout_index (MetaSeatNative *seat); - -void meta_seat_native_set_keyboard_repeat (MetaSeatNative *seat, - gboolean repeat, - uint32_t delay, - uint32_t interval); - -void meta_seat_native_release_touch_slots (MetaSeatNative *seat, - guint base_slot); - -MetaBarrierManagerNative * meta_seat_native_get_barrier_manager (MetaSeatNative *seat); - -MetaBackend * meta_seat_native_get_backend (MetaSeatNative *seat); - -void meta_seat_native_set_pointer_constraint (MetaSeatNative *seat, - MetaPointerConstraintImpl *constraint_impl); -MetaCursorRenderer * meta_seat_native_maybe_ensure_cursor_renderer (MetaSeatNative *seat, - ClutterInputDevice *device); - -void meta_seat_native_set_viewports (MetaSeatNative *seat, - MetaViewportInfo *viewports); - -#endif /* META_SEAT_NATIVE_H */ diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c deleted file mode 100644 index e1f9fedb2..000000000 --- a/src/backends/native/meta-stage-native.c +++ /dev/null @@ -1,191 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * - * 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: - * Jonas Ådahl <jadahl@gmail.com> - */ - -#include "config.h" - -#include "backends/native/meta-stage-native.h" - -#include "backends/meta-backend-private.h" -#include "backends/native/meta-crtc-virtual.h" -#include "backends/native/meta-cursor-renderer-native.h" -#include "backends/native/meta-renderer-native.h" -#include "meta/meta-backend.h" -#include "meta/meta-monitor-manager.h" -#include "meta/util.h" - -static GQuark quark_view_frame_closure = 0; - -struct _MetaStageNative -{ - MetaStageImpl parent; - - CoglClosure *frame_closure; - - int64_t presented_frame_counter_sync; - int64_t presented_frame_counter_complete; -}; - -static ClutterStageWindowInterface *clutter_stage_window_parent_iface = NULL; - -static void -clutter_stage_window_iface_init (ClutterStageWindowInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaStageNative, meta_stage_native, - META_TYPE_STAGE_IMPL, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, - clutter_stage_window_iface_init)) - -void -meta_stage_native_rebuild_views (MetaStageNative *stage_native) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - ClutterActor *stage = meta_backend_get_stage (backend); - - meta_renderer_rebuild_views (renderer); - clutter_stage_clear_stage_views (CLUTTER_STAGE (stage)); -} - -static gboolean -meta_stage_native_can_clip_redraws (ClutterStageWindow *stage_window) -{ - return TRUE; -} - -static void -meta_stage_native_get_geometry (ClutterStageWindow *stage_window, - cairo_rectangle_int_t *geometry) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - if (monitor_manager) - { - int width, height; - - meta_monitor_manager_get_screen_size (monitor_manager, &width, &height); - *geometry = (cairo_rectangle_int_t) { - .width = width, - .height = height, - }; - } - else - { - *geometry = (cairo_rectangle_int_t) { - .width = 1, - .height = 1, - }; - } -} - -static GList * -meta_stage_native_get_views (ClutterStageWindow *stage_window) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - return meta_renderer_get_views (renderer); -} - -static void -meta_stage_native_prepare_frame (ClutterStageWindow *stage_window, - ClutterStageView *stage_view, - ClutterFrame *frame) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (cursor_renderer); - - meta_renderer_native_prepare_frame (renderer_native, - META_RENDERER_VIEW (stage_view), - frame); - meta_cursor_renderer_native_prepare_frame (cursor_renderer_native, - META_RENDERER_VIEW (stage_view)); -} - -static void -meta_stage_native_redraw_view (ClutterStageWindow *stage_window, - ClutterStageView *view, - ClutterFrame *frame) -{ - MetaCrtc *crtc; - - clutter_stage_window_parent_iface->redraw_view (stage_window, view, frame); - - crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (view)); - if (META_IS_CRTC_VIRTUAL (crtc)) - { - g_warn_if_fail (!clutter_frame_has_result (frame)); - - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - } -} - -static void -meta_stage_native_finish_frame (ClutterStageWindow *stage_window, - ClutterStageView *stage_view, - ClutterFrame *frame) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - meta_renderer_native_finish_frame (META_RENDERER_NATIVE (renderer), - META_RENDERER_VIEW (stage_view), - frame); - - if (!clutter_frame_has_result (frame)) - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); -} - -static void -meta_stage_native_init (MetaStageNative *stage_native) -{ - stage_native->presented_frame_counter_sync = -1; - stage_native->presented_frame_counter_complete = -1; -} - -static void -meta_stage_native_class_init (MetaStageNativeClass *klass) -{ - quark_view_frame_closure = - g_quark_from_static_string ("-meta-native-stage-view-frame-closure"); -} - -static void -clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) -{ - clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface); - - iface->can_clip_redraws = meta_stage_native_can_clip_redraws; - iface->get_geometry = meta_stage_native_get_geometry; - iface->get_views = meta_stage_native_get_views; - iface->prepare_frame = meta_stage_native_prepare_frame; - iface->redraw_view = meta_stage_native_redraw_view; - iface->finish_frame = meta_stage_native_finish_frame; -} diff --git a/src/backends/native/meta-stage-native.h b/src/backends/native/meta-stage-native.h deleted file mode 100644 index 5f33e1f9a..000000000 --- a/src/backends/native/meta-stage-native.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * - * 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: - * Jonas Ådahl <jadahl@gmail.com> - */ - -#ifndef META_STAGE_NATIVE_H -#define META_STAGE_NATIVE_H - -#include "backends/meta-stage-impl-private.h" -#include "clutter/clutter-mutter.h" - -#define META_TYPE_STAGE_NATIVE (meta_stage_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaStageNative, meta_stage_native, - META, STAGE_NATIVE, MetaStageImpl) - -void meta_stage_native_rebuild_views (MetaStageNative *stage_native); - -#endif /* META_STAGE_NATIVE_H */ diff --git a/src/backends/native/meta-udev.c b/src/backends/native/meta-udev.c deleted file mode 100644 index 9fd84e98b..000000000 --- a/src/backends/native/meta-udev.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2018 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. - * - */ - -#include "config.h" - -#include "backends/native/meta-udev.h" - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-launcher.h" - -#define DRM_CARD_UDEV_DEVICE_TYPE "drm_minor" - -enum -{ - HOTPLUG, - DEVICE_ADDED, - DEVICE_REMOVED, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS]; - -struct _MetaUdev -{ - GObject parent; - - MetaBackendNative *backend_native; - - GUdevClient *gudev_client; - - gulong uevent_handler_id; -}; - -G_DEFINE_TYPE (MetaUdev, meta_udev, G_TYPE_OBJECT) - -gboolean -meta_is_udev_device_platform_device (GUdevDevice *device) -{ - g_autoptr (GUdevDevice) platform_device = NULL; - - platform_device = g_udev_device_get_parent_with_subsystem (device, - "platform", - NULL); - return !!platform_device; -} - -gboolean -meta_is_udev_device_boot_vga (GUdevDevice *device) -{ - g_autoptr (GUdevDevice) pci_device = NULL; - - pci_device = g_udev_device_get_parent_with_subsystem (device, "pci", NULL); - if (!pci_device) - return FALSE; - - return g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga") == 1; -} - -static gboolean -meta_has_udev_device_tag (GUdevDevice *device, - const char *tag) -{ - const char * const * tags; - g_autoptr (GUdevDevice) platform_device = NULL; - - tags = g_udev_device_get_tags (device); - if (tags && g_strv_contains (tags, tag)) - return TRUE; - - platform_device = g_udev_device_get_parent_with_subsystem (device, - "platform", - NULL); - - if (platform_device) - return meta_has_udev_device_tag (platform_device, tag); - else - return FALSE; -} - -gboolean -meta_is_udev_device_disable_modifiers (GUdevDevice *device) -{ - return meta_has_udev_device_tag (device, - "mutter-device-disable-kms-modifiers"); -} - -gboolean -meta_is_udev_device_ignore (GUdevDevice *device) -{ - return meta_has_udev_device_tag (device, "mutter-device-ignore"); -} - -gboolean -meta_is_udev_device_preferred_primary (GUdevDevice *device) -{ - const char * const * tags; - - tags = g_udev_device_get_tags (device); - if (!tags) - return FALSE; - - return g_strv_contains (tags, "mutter-device-preferred-primary"); -} - -gboolean -meta_udev_is_drm_device (MetaUdev *udev, - GUdevDevice *device) -{ - const char *seat_id; - const char *device_type; - const char *device_seat; - - /* Filter out devices that are not character device, like card0-VGA-1. */ - if (g_udev_device_get_device_type (device) != G_UDEV_DEVICE_TYPE_CHAR) - return FALSE; - - device_type = g_udev_device_get_property (device, "DEVTYPE"); - if (g_strcmp0 (device_type, DRM_CARD_UDEV_DEVICE_TYPE) != 0) - return FALSE; - - device_seat = g_udev_device_get_property (device, "ID_SEAT"); - if (!device_seat) - { - /* When ID_SEAT is not set, it means seat0. */ - device_seat = "seat0"; - } - - /* Skip devices that do not belong to our seat. */ - seat_id = meta_backend_native_get_seat_id (udev->backend_native); - if (g_strcmp0 (seat_id, device_seat)) - return FALSE; - - return TRUE; -} - -GList * -meta_udev_list_drm_devices (MetaUdev *udev, - GError **error) -{ - g_autoptr (GUdevEnumerator) enumerator = NULL; - GList *devices; - GList *l; - - enumerator = g_udev_enumerator_new (udev->gudev_client); - - g_udev_enumerator_add_match_name (enumerator, "card*"); - g_udev_enumerator_add_match_tag (enumerator, "seat"); - - /* - * We need to explicitly match the subsystem for now. - * https://bugzilla.gnome.org/show_bug.cgi?id=773224 - */ - g_udev_enumerator_add_match_subsystem (enumerator, "drm"); - - devices = g_udev_enumerator_execute (enumerator); - if (!devices) - return NULL; - - for (l = devices; l;) - { - GUdevDevice *device = l->data; - GList *l_next = l->next; - - if (!meta_udev_is_drm_device (udev, device)) - { - g_object_unref (device); - devices = g_list_delete_link (devices, l); - } - - l = l_next; - } - - return devices; -} - -static void -on_uevent (GUdevClient *client, - const char *action, - GUdevDevice *device, - gpointer user_data) -{ - MetaUdev *udev = META_UDEV (user_data); - - if (!g_udev_device_get_device_file (device)) - return; - - if (g_str_equal (action, "add")) - g_signal_emit (udev, signals[DEVICE_ADDED], 0, device); - else if (g_str_equal (action, "remove")) - g_signal_emit (udev, signals[DEVICE_REMOVED], 0, device); - - if (g_udev_device_get_property_as_boolean (device, "HOTPLUG")) - g_signal_emit (udev, signals[HOTPLUG], 0); -} - -MetaUdev * -meta_udev_new (MetaBackendNative *backend_native) -{ - MetaUdev *udev; - - udev = g_object_new (META_TYPE_UDEV, NULL); - udev->backend_native = backend_native; - - return udev; -} - -static void -meta_udev_finalize (GObject *object) -{ - MetaUdev *udev = META_UDEV (object); - - g_clear_signal_handler (&udev->uevent_handler_id, udev->gudev_client); - g_clear_object (&udev->gudev_client); - - G_OBJECT_CLASS (meta_udev_parent_class)->finalize (object); -} - -static void -meta_udev_init (MetaUdev *udev) -{ - const char *subsystems[] = { "drm", NULL }; - - udev->gudev_client = g_udev_client_new (subsystems); - udev->uevent_handler_id = g_signal_connect (udev->gudev_client, - "uevent", - G_CALLBACK (on_uevent), udev); -} - -static void -meta_udev_class_init (MetaUdevClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_udev_finalize; - - signals[HOTPLUG] = - g_signal_new ("hotplug", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - signals[DEVICE_ADDED] = - g_signal_new ("device-added", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_UDEV_TYPE_DEVICE); - signals[DEVICE_REMOVED] = - g_signal_new ("device-removed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_UDEV_TYPE_DEVICE); -} diff --git a/src/backends/native/meta-udev.h b/src/backends/native/meta-udev.h deleted file mode 100644 index 7b179329e..000000000 --- a/src/backends/native/meta-udev.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2018 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. - * - */ - -#ifndef META_UDEV_H -#define META_UDEV_H - -#include <gudev/gudev.h> - -#include "backends/native/meta-backend-native-types.h" - -#define META_TYPE_UDEV (meta_udev_get_type ()) -G_DECLARE_FINAL_TYPE (MetaUdev, meta_udev, META, UDEV, GObject) - -gboolean meta_is_udev_device_platform_device (GUdevDevice *device); - -gboolean meta_is_udev_device_boot_vga (GUdevDevice *device); - -gboolean meta_is_udev_device_disable_modifiers (GUdevDevice *device); - -gboolean meta_is_udev_device_ignore (GUdevDevice *device); - -gboolean meta_is_udev_device_preferred_primary (GUdevDevice *device); - -gboolean meta_udev_is_drm_device (MetaUdev *udev, - GUdevDevice *device); - -GList * meta_udev_list_drm_devices (MetaUdev *udev, - GError **error); - -MetaUdev * meta_udev_new (MetaBackendNative *backend_native); - -#endif /* META_UDEV_H */ diff --git a/src/backends/native/meta-virtual-input-device-native.c b/src/backends/native/meta-virtual-input-device-native.c deleted file mode 100644 index d2d13748a..000000000 --- a/src/backends/native/meta-virtual-input-device-native.c +++ /dev/null @@ -1,1110 +0,0 @@ -/* - * Copyright (C) 2016 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Jonas Ådahl <jadahl@gmail.com> - */ - -#include "config.h" - -#include <glib-object.h> -#include <linux/input.h> - -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-seat-native.h" -#include "backends/native/meta-virtual-input-device-native.h" -#include "clutter/clutter-mutter.h" -#include "meta/util.h" - -enum -{ - PROP_0, - - PROP_SEAT, - PROP_SLOT_BASE, - - PROP_LAST -}; - -static GParamSpec *obj_props[PROP_LAST]; - -typedef struct _ImplState ImplState; - -struct _ImplState -{ - ClutterInputDevice *device; - int button_count[KEY_CNT]; -}; - -struct _MetaVirtualInputDeviceNative -{ - ClutterVirtualInputDevice parent; - - MetaSeatNative *seat; - guint slot_base; - ImplState *impl_state; -}; - -typedef struct -{ - uint64_t time_us; - double x; - double y; -} MetaVirtualEventMotion; - -typedef struct -{ - uint64_t time_us; - uint32_t button; - ClutterButtonState button_state; -} MetaVirtualEventButton; - -typedef struct -{ - uint64_t time_us; - double dx; - double dy; - ClutterScrollDirection direction; - ClutterScrollSource scroll_source; - ClutterScrollFinishFlags finish_flags; -} MetaVirtualEventScroll; - -typedef struct -{ - uint64_t time_us; - uint32_t key; - ClutterKeyState key_state; -} MetaVirtualEventKey; - -typedef struct -{ - uint64_t time_us; - int device_slot; - double x; - double y; -} MetaVirtualEventTouch; - -G_DEFINE_TYPE (MetaVirtualInputDeviceNative, - meta_virtual_input_device_native, - CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE) - -typedef enum _EvdevButtonType -{ - EVDEV_BUTTON_TYPE_NONE, - EVDEV_BUTTON_TYPE_KEY, - EVDEV_BUTTON_TYPE_BUTTON, -} EvdevButtonType; - -static int -update_button_count_in_impl (MetaVirtualInputDeviceNative *virtual_evdev, - uint32_t button, - uint32_t state) -{ - if (state) - return ++virtual_evdev->impl_state->button_count[button]; - else - return --virtual_evdev->impl_state->button_count[button]; -} - -static EvdevButtonType -get_button_type (uint16_t code) -{ - switch (code) - { - case BTN_TOOL_PEN: - case BTN_TOOL_RUBBER: - case BTN_TOOL_BRUSH: - case BTN_TOOL_PENCIL: - case BTN_TOOL_AIRBRUSH: - case BTN_TOOL_MOUSE: - case BTN_TOOL_LENS: - case BTN_TOOL_QUINTTAP: - case BTN_TOOL_DOUBLETAP: - case BTN_TOOL_TRIPLETAP: - case BTN_TOOL_QUADTAP: - case BTN_TOOL_FINGER: - case BTN_TOUCH: - return EVDEV_BUTTON_TYPE_NONE; - } - - if (code >= KEY_ESC && code <= KEY_MICMUTE) - return EVDEV_BUTTON_TYPE_KEY; - if (code >= BTN_MISC && code <= BTN_GEAR_UP) - return EVDEV_BUTTON_TYPE_BUTTON; - if (code >= KEY_OK && code <= KEY_LIGHTS_TOGGLE) - return EVDEV_BUTTON_TYPE_KEY; - if (code >= BTN_DPAD_UP && code <= BTN_DPAD_RIGHT) - return EVDEV_BUTTON_TYPE_BUTTON; - if (code >= KEY_ALS_TOGGLE && code <= KEY_KBDINPUTASSIST_CANCEL) - return EVDEV_BUTTON_TYPE_KEY; - if (code >= BTN_TRIGGER_HAPPY && code <= BTN_TRIGGER_HAPPY40) - return EVDEV_BUTTON_TYPE_BUTTON; - return EVDEV_BUTTON_TYPE_NONE; -} - -static gboolean -release_device_in_impl (GTask *task) -{ - ImplState *impl_state = g_task_get_task_data (task); - MetaInputDeviceNative *device_native; - MetaSeatImpl *seat_impl; - int code; - uint64_t time_us; - ClutterEvent *device_event; - - device_native = META_INPUT_DEVICE_NATIVE (impl_state->device); - seat_impl = meta_input_device_native_get_seat_impl (device_native); - time_us = g_get_monotonic_time (); - - meta_topic (META_DEBUG_INPUT, - "Releasing pressed buttons while destroying virtual input device " - "(device %p)", device_native); - - for (code = 0; code < G_N_ELEMENTS (impl_state->button_count); code++) - { - if (impl_state->button_count[code] == 0) - continue; - - switch (get_button_type (code)) - { - case EVDEV_BUTTON_TYPE_KEY: - meta_seat_impl_notify_key_in_impl (seat_impl, - impl_state->device, - time_us, - code, - CLUTTER_KEY_STATE_RELEASED, - TRUE); - break; - case EVDEV_BUTTON_TYPE_BUTTON: - meta_seat_impl_notify_button_in_impl (seat_impl, - impl_state->device, - time_us, - code, - CLUTTER_BUTTON_STATE_RELEASED); - break; - case EVDEV_BUTTON_TYPE_NONE: - g_assert_not_reached (); - } - } - - device_event = clutter_event_new (CLUTTER_DEVICE_REMOVED); - clutter_event_set_device (device_event, impl_state->device); - _clutter_event_push (device_event, FALSE); - - g_clear_object (&impl_state->device); - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -static gboolean -notify_relative_motion_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventMotion *event = g_task_get_task_data (task); - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - meta_seat_impl_notify_relative_motion_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - event->x, event->y, - event->x, event->y); - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_relative_motion (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - double dx, - double dy) -{ - MetaVirtualEventMotion *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventMotion, 1); - event->time_us = time_us; - event->x = dx; - event->y = dy; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_relative_motion_in_impl); - g_object_unref (task); -} - -static gboolean -notify_absolute_motion_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventMotion *event = g_task_get_task_data (task); - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - meta_seat_impl_notify_absolute_motion_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - event->x, event->y, - NULL); - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - double x, - double y) -{ - MetaVirtualEventMotion *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventMotion, 1); - event->time_us = time_us; - event->x = x; - event->y = y; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_absolute_motion_in_impl); - g_object_unref (task); -} - -static int -translate_to_evdev_button (int clutter_button) -{ - switch (clutter_button) - { - case CLUTTER_BUTTON_PRIMARY: - return BTN_LEFT; - case CLUTTER_BUTTON_SECONDARY: - return BTN_RIGHT; - case CLUTTER_BUTTON_MIDDLE: - return BTN_MIDDLE; - default: - /* - * For compatibility reasons, all additional buttons go after the old - * 4-7 scroll ones. - */ - return clutter_button + (BTN_LEFT - 1) - 4; - } -} - -static gboolean -notify_button_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventButton *event = g_task_get_task_data (task); - int button_count; - int evdev_button; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - evdev_button = translate_to_evdev_button (event->button); - - if (get_button_type (evdev_button) != EVDEV_BUTTON_TYPE_BUTTON) - { - g_warning ("Unknown/invalid virtual device button 0x%x pressed", - evdev_button); - goto out; - } - - button_count = update_button_count_in_impl (virtual_evdev, evdev_button, - event->button_state); - if (button_count < 0 || button_count > 1) - { - g_warning ("Received multiple virtual 0x%x button %s (ignoring)", evdev_button, - event->button_state == CLUTTER_BUTTON_STATE_PRESSED ? - "presses" : "releases"); - update_button_count_in_impl (virtual_evdev, evdev_button, 1 - event->button_state); - goto out; - } - - meta_topic (META_DEBUG_INPUT, - "Emitting virtual button-%s of button 0x%x (device %p)", - event->button_state == CLUTTER_BUTTON_STATE_PRESSED ? - "press" : "release", - evdev_button, virtual_evdev); - - meta_seat_impl_notify_button_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - evdev_button, - event->button_state); - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_button (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t button, - ClutterButtonState button_state) -{ - MetaVirtualEventButton *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventButton, 1); - event->time_us = time_us; - event->button = button; - event->button_state = button_state; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_button_in_impl); - g_object_unref (task); -} - -static gboolean -notify_key_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventKey *event = g_task_get_task_data (task); - int key_count; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - if (get_button_type (event->key) != EVDEV_BUTTON_TYPE_KEY) - { - g_warning ("Unknown/invalid virtual device key 0x%x pressed", event->key); - goto out; - } - - key_count = update_button_count_in_impl (virtual_evdev, event->key, event->key_state); - if (key_count < 0 || key_count > 1) - { - g_warning ("Received multiple virtual 0x%x key %s (ignoring)", event->key, - event->key_state == CLUTTER_KEY_STATE_PRESSED ? - "presses" : "releases"); - update_button_count_in_impl (virtual_evdev, event->key, 1 - event->key_state); - goto out; - } - - meta_topic (META_DEBUG_INPUT, - "Emitting virtual key-%s of key 0x%x (device %p)", - event->key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release", - event->key, virtual_evdev); - - meta_seat_impl_notify_key_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - event->key, - event->key_state, - TRUE); - - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_key (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t key, - ClutterKeyState key_state) -{ - MetaVirtualEventKey *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventKey, 1); - event->time_us = time_us; - event->key = key; - event->key_state = key_state; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_key_in_impl); - g_object_unref (task); -} - -static gboolean -pick_keycode_for_keyval_in_current_group_in_impl (ClutterVirtualInputDevice *virtual_device, - guint keyval, - guint *keycode_out, - guint *level_out) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - ClutterBackend *backend; - ClutterKeymap *keymap; - struct xkb_keymap *xkb_keymap; - struct xkb_state *state; - guint keycode, layout; - xkb_keycode_t min_keycode, max_keycode; - - backend = clutter_get_default_backend (); - keymap = clutter_seat_get_keymap (clutter_backend_get_default_seat (backend)); - xkb_keymap = meta_keymap_native_get_keyboard_map_in_impl (META_KEYMAP_NATIVE (keymap)); - state = meta_seat_impl_get_xkb_state_in_impl (virtual_evdev->seat->impl); - - layout = xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE); - min_keycode = xkb_keymap_min_keycode (xkb_keymap); - max_keycode = xkb_keymap_max_keycode (xkb_keymap); - for (keycode = min_keycode; keycode < max_keycode; keycode++) - { - gint num_levels, level; - num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout); - for (level = 0; level < num_levels; level++) - { - const xkb_keysym_t *syms; - gint num_syms, sym; - num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms); - for (sym = 0; sym < num_syms; sym++) - { - if (syms[sym] == keyval) - { - *keycode_out = keycode; - if (level_out) - *level_out = level; - return TRUE; - } - } - } - } - - return FALSE; -} - -static void -apply_level_modifiers_in_impl (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t level, - uint32_t key_state) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - guint keysym, keycode, evcode; - - if (level == 0) - return; - - if (level == 1) - { - keysym = XKB_KEY_Shift_L; - } - else if (level == 2) - { - keysym = XKB_KEY_ISO_Level3_Shift; - } - else - { - g_warning ("Unhandled level: %d", level); - return; - } - - if (!pick_keycode_for_keyval_in_current_group_in_impl (virtual_device, keysym, - &keycode, NULL)) - return; - - evcode = meta_xkb_keycode_to_evdev (keycode); - - meta_topic (META_DEBUG_INPUT, - "Emitting virtual key-%s of modifier key 0x%x (device %p)", - key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release", - evcode, virtual_device); - - meta_seat_impl_notify_key_in_impl (virtual_evdev->seat->impl, - virtual_evdev->impl_state->device, - time_us, - evcode, - key_state, - TRUE); -} - -static gboolean -notify_keyval_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - ClutterVirtualInputDevice *virtual_device = - CLUTTER_VIRTUAL_INPUT_DEVICE (virtual_evdev); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventKey *event = g_task_get_task_data (task); - int key_count; - guint keycode = 0, level = 0, evcode = 0; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - if (!pick_keycode_for_keyval_in_current_group_in_impl (virtual_device, - event->key, - &keycode, &level)) - { - g_warning ("No keycode found for keyval %x in current group", event->key); - goto out; - } - - evcode = meta_xkb_keycode_to_evdev (keycode); - - if (get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY) - { - g_warning ("Unknown/invalid virtual device key 0x%x pressed", evcode); - goto out; - } - - key_count = update_button_count_in_impl (virtual_evdev, evcode, event->key_state); - if (key_count < 0 || key_count > 1) - { - g_warning ("Received multiple virtual 0x%x key %s (ignoring)", evcode, - event->key_state == CLUTTER_KEY_STATE_PRESSED ? - "presses" : "releases"); - update_button_count_in_impl (virtual_evdev, evcode, 1 - event->key_state); - goto out; - } - - meta_topic (META_DEBUG_INPUT, - "Emitting virtual key-%s of key 0x%x with modifier level %d, " - "press count %d (device %p)", - event->key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release", - evcode, level, key_count, virtual_evdev); - - if (event->key_state) - { - apply_level_modifiers_in_impl (virtual_device, event->time_us, - level, event->key_state); - } - - meta_seat_impl_notify_key_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - evcode, - event->key_state, - TRUE); - - if (!event->key_state) - { - apply_level_modifiers_in_impl (virtual_device, event->time_us, - level, event->key_state); - } - - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_keyval (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t keyval, - ClutterKeyState key_state) -{ - MetaVirtualEventKey *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventKey, 1); - event->time_us = time_us; - event->key = keyval; - event->key_state = key_state; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_keyval_in_impl); - g_object_unref (task); -} - -static void -direction_to_discrete (ClutterScrollDirection direction, - double *discrete_dx, - double *discrete_dy) -{ - switch (direction) - { - case CLUTTER_SCROLL_UP: - *discrete_dx = 0.0; - *discrete_dy = -1.0; - break; - case CLUTTER_SCROLL_DOWN: - *discrete_dx = 0.0; - *discrete_dy = 1.0; - break; - case CLUTTER_SCROLL_LEFT: - *discrete_dx = -1.0; - *discrete_dy = 0.0; - break; - case CLUTTER_SCROLL_RIGHT: - *discrete_dx = 1.0; - *discrete_dy = 0.0; - break; - case CLUTTER_SCROLL_SMOOTH: - g_assert_not_reached (); - break; - } -} - -static gboolean -notify_discrete_scroll_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventScroll *event = g_task_get_task_data (task); - double discrete_dx = 0.0, discrete_dy = 0.0; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - direction_to_discrete (event->direction, &discrete_dx, &discrete_dy); - - meta_seat_impl_notify_discrete_scroll_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - discrete_dx, discrete_dy, - event->scroll_source); - - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_discrete_scroll (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - ClutterScrollDirection direction, - ClutterScrollSource scroll_source) -{ - MetaVirtualEventScroll *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventScroll, 1); - event->time_us = time_us; - event->direction = direction; - event->scroll_source = scroll_source; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_discrete_scroll_in_impl); - g_object_unref (task); -} - -static gboolean -notify_scroll_continuous_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventScroll *event = g_task_get_task_data (task); - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - meta_seat_impl_notify_scroll_continuous_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - event->dx, event->dy, - event->scroll_source, - CLUTTER_SCROLL_FINISHED_NONE); - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_scroll_continuous (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - double dx, - double dy, - ClutterScrollSource scroll_source, - ClutterScrollFinishFlags finish_flags) -{ - MetaVirtualEventScroll *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventScroll, 1); - event->time_us = time_us; - event->dx = dx; - event->dy = dy; - event->scroll_source = scroll_source; - event->finish_flags = finish_flags; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_scroll_continuous_in_impl); - g_object_unref (task); -} - -static gboolean -notify_touch_down_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventTouch *event = g_task_get_task_data (task); - MetaTouchState *touch_state; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - touch_state = meta_seat_impl_acquire_touch_state_in_impl (seat, - event->device_slot); - if (!touch_state) - goto out; - - touch_state->coords.x = event->x; - touch_state->coords.y = event->y; - - meta_seat_impl_notify_touch_event_in_impl (seat, - virtual_evdev->impl_state->device, - CLUTTER_TOUCH_BEGIN, - event->time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_touch_down (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - int device_slot, - double x, - double y) -{ - MetaVirtualEventTouch *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventTouch, 1); - event->time_us = time_us; - event->device_slot = virtual_evdev->slot_base + (guint) device_slot; - event->x = x; - event->y = y; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_touch_down_in_impl); - g_object_unref (task); -} - -static gboolean -notify_touch_motion_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventTouch *event = g_task_get_task_data (task); - MetaTouchState *touch_state; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat, - event->device_slot); - if (!touch_state) - goto out; - - touch_state->coords.x = event->x; - touch_state->coords.y = event->y; - - meta_seat_impl_notify_touch_event_in_impl (seat, - virtual_evdev->impl_state->device, - CLUTTER_TOUCH_UPDATE, - event->time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_touch_motion (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - int device_slot, - double x, - double y) -{ - MetaVirtualEventTouch *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventTouch, 1); - event->time_us = time_us; - event->device_slot = virtual_evdev->slot_base + (guint) device_slot; - event->x = x; - event->y = y; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_touch_motion_in_impl); - g_object_unref (task); -} - -static gboolean -notify_touch_up_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventTouch *event = g_task_get_task_data (task); - MetaTouchState *touch_state; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat, - event->device_slot); - if (!touch_state) - goto out; - - meta_seat_impl_notify_touch_event_in_impl (seat, - virtual_evdev->impl_state->device, - CLUTTER_TOUCH_END, - event->time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - - meta_seat_impl_release_touch_state_in_impl (virtual_evdev->seat->impl, - touch_state->seat_slot); - - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_touch_up (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - int device_slot) -{ - MetaVirtualEventTouch *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventTouch, 1); - event->time_us = time_us; - event->device_slot = virtual_evdev->slot_base + (guint) device_slot; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_touch_up_in_impl); - g_object_unref (task); -} - -static void -meta_virtual_input_device_native_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT: - g_value_set_pointer (value, virtual_evdev->seat); - break; - case PROP_SLOT_BASE: - g_value_set_uint (value, virtual_evdev->slot_base); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_virtual_input_device_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT: - virtual_evdev->seat = g_value_get_pointer (value); - break; - case PROP_SLOT_BASE: - virtual_evdev->slot_base = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_virtual_input_device_native_constructed (GObject *object) -{ - ClutterVirtualInputDevice *virtual_device = - CLUTTER_VIRTUAL_INPUT_DEVICE (object); - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (object); - ClutterInputDeviceType device_type; - ClutterEvent *device_event = NULL; - - device_type = clutter_virtual_input_device_get_device_type (virtual_device); - - meta_topic (META_DEBUG_INPUT, - "Creating new virtual input device of type %d (%p)", - device_type, virtual_device); - - virtual_evdev->impl_state = g_new0 (ImplState, 1); - virtual_evdev->impl_state->device = - meta_input_device_native_new_virtual (virtual_evdev->seat->impl, - device_type, - CLUTTER_INPUT_MODE_PHYSICAL); - - device_event = clutter_event_new (CLUTTER_DEVICE_ADDED); - clutter_event_set_device (device_event, virtual_evdev->impl_state->device); - _clutter_event_push (device_event, FALSE); -} - -static void -impl_state_free (ImplState *impl_state) -{ - g_warn_if_fail (!impl_state->device); - g_free (impl_state); -} - -static void -meta_virtual_input_device_native_dispose (GObject *object) -{ - ClutterVirtualInputDevice *virtual_device = - CLUTTER_VIRTUAL_INPUT_DEVICE (object); - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (object); - GObjectClass *object_class = - G_OBJECT_CLASS (meta_virtual_input_device_native_parent_class); - - if (virtual_evdev->impl_state) - { - GTask *task; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, virtual_evdev->impl_state, - (GDestroyNotify) impl_state_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) release_device_in_impl); - g_object_unref (task); - - virtual_evdev->impl_state = NULL; - } - - meta_seat_native_release_touch_slots (virtual_evdev->seat, - virtual_evdev->slot_base); - - object_class->dispose (object); -} - -static void -meta_virtual_input_device_native_init (MetaVirtualInputDeviceNative *virtual_device_evdev) -{ -} - -static void -meta_virtual_input_device_native_class_init (MetaVirtualInputDeviceNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterVirtualInputDeviceClass *virtual_input_device_class = - CLUTTER_VIRTUAL_INPUT_DEVICE_CLASS (klass); - - object_class->get_property = meta_virtual_input_device_native_get_property; - object_class->set_property = meta_virtual_input_device_native_set_property; - object_class->constructed = meta_virtual_input_device_native_constructed; - object_class->dispose = meta_virtual_input_device_native_dispose; - - virtual_input_device_class->notify_relative_motion = meta_virtual_input_device_native_notify_relative_motion; - virtual_input_device_class->notify_absolute_motion = meta_virtual_input_device_native_notify_absolute_motion; - virtual_input_device_class->notify_button = meta_virtual_input_device_native_notify_button; - virtual_input_device_class->notify_key = meta_virtual_input_device_native_notify_key; - virtual_input_device_class->notify_keyval = meta_virtual_input_device_native_notify_keyval; - virtual_input_device_class->notify_discrete_scroll = meta_virtual_input_device_native_notify_discrete_scroll; - virtual_input_device_class->notify_scroll_continuous = meta_virtual_input_device_native_notify_scroll_continuous; - virtual_input_device_class->notify_touch_down = meta_virtual_input_device_native_notify_touch_down; - virtual_input_device_class->notify_touch_motion = meta_virtual_input_device_native_notify_touch_motion; - virtual_input_device_class->notify_touch_up = meta_virtual_input_device_native_notify_touch_up; - - obj_props[PROP_SEAT] = g_param_spec_pointer ("seat", - "Seat", - "Seat", - CLUTTER_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - obj_props[PROP_SLOT_BASE] = g_param_spec_uint ("slot-base", - "Slot base", - "Base for touch slots", - 0, G_MAXUINT, 0, - CLUTTER_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_properties (object_class, PROP_LAST, obj_props); -} diff --git a/src/backends/native/meta-virtual-input-device-native.h b/src/backends/native/meta-virtual-input-device-native.h deleted file mode 100644 index 28d218abb..000000000 --- a/src/backends/native/meta-virtual-input-device-native.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2016 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - * - * Author: Jonas Ådahl <jadahl@gmail.com> - */ - -#ifndef META_VIRTUAL_INPUT_DEVICE_NATIVE_H -#define META_VIRTUAL_INPUT_DEVICE_NATIVE_H - -#include "clutter/clutter-virtual-input-device.h" - -#define META_TYPE_VIRTUAL_INPUT_DEVICE_NATIVE (meta_virtual_input_device_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaVirtualInputDeviceNative, - meta_virtual_input_device_native, - META, VIRTUAL_INPUT_DEVICE_NATIVE, - ClutterVirtualInputDevice) - -#endif /* META_VIRTUAL_INPUT_DEVICE_NATIVE_H */ diff --git a/src/backends/native/meta-virtual-monitor-native.c b/src/backends/native/meta-virtual-monitor-native.c deleted file mode 100644 index 3f81f4180..000000000 --- a/src/backends/native/meta-virtual-monitor-native.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * 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. - * - */ - -#include "config.h" - -#include "backends/native/meta-virtual-monitor-native.h" - -#include "backends/native/meta-crtc-mode-virtual.h" -#include "backends/native/meta-crtc-virtual.h" -#include "backends/native/meta-output-virtual.h" - -struct _MetaVirtualMonitorNative -{ - MetaVirtualMonitor parent; - - uint64_t id; -}; - -#define VIRTUAL_OUTPUT_ID_BIT (((uint64_t) 1) << 63) - -G_DEFINE_TYPE (MetaVirtualMonitorNative, meta_virtual_monitor_native, - META_TYPE_VIRTUAL_MONITOR) - -uint64_t -meta_virtual_monitor_native_get_id (MetaVirtualMonitorNative *virtual_monitor_native) -{ - return virtual_monitor_native->id; -} - -MetaVirtualMonitorNative * -meta_virtual_monitor_native_new (uint64_t id, - const MetaVirtualMonitorInfo *info) -{ - MetaVirtualMonitorNative *virtual_monitor_native; - MetaCrtcVirtual *crtc_virtual; - MetaCrtcModeVirtual *crtc_mode_virtual; - MetaOutputVirtual *output_virtual; - - crtc_virtual = meta_crtc_virtual_new (id); - crtc_mode_virtual = meta_crtc_mode_virtual_new (id, info); - output_virtual = meta_output_virtual_new (id, info, - crtc_virtual, - crtc_mode_virtual); - - virtual_monitor_native = g_object_new (META_TYPE_VIRTUAL_MONITOR_NATIVE, - "crtc", crtc_virtual, - "crtc-mode", crtc_mode_virtual, - "output", output_virtual, - NULL); - virtual_monitor_native->id = id; - - return virtual_monitor_native; -} - -static void -meta_virtual_monitor_native_init (MetaVirtualMonitorNative *virtual_monitor_native) -{ -} - -static void -meta_virtual_monitor_native_class_init (MetaVirtualMonitorNativeClass *klass) -{ -} diff --git a/src/backends/native/meta-virtual-monitor-native.h b/src/backends/native/meta-virtual-monitor-native.h deleted file mode 100644 index d1a0ced64..000000000 --- a/src/backends/native/meta-virtual-monitor-native.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * 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. - * - */ - -#ifndef META_VIRTUAL_MONITOR_NATIVE_H -#define META_VIRTUAL_MONITOR_NATIVE_H - -#include <stdint.h> - -#include "backends/meta-virtual-monitor.h" -#include "backends/meta-backend-types.h" - -#define META_TYPE_VIRTUAL_MONITOR_NATIVE (meta_virtual_monitor_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaVirtualMonitorNative, meta_virtual_monitor_native, - META, VIRTUAL_MONITOR_NATIVE, - MetaVirtualMonitor) - -uint64_t meta_virtual_monitor_native_get_id (MetaVirtualMonitorNative *virtual_monitor_native); - -MetaCrtcMode * meta_virtual_monitor_native_get_crtc_mode (MetaVirtualMonitorNative *virtual_monitor_native); - -MetaCrtc * meta_virtual_monitor_native_get_crtc (MetaVirtualMonitorNative *virtual_monitor_native); - -MetaOutput * meta_virtual_monitor_native_get_output (MetaVirtualMonitorNative *virtual_monitor_native); - -MetaVirtualMonitorNative * meta_virtual_monitor_native_new (uint64_t id, - const MetaVirtualMonitorInfo *info); - -#endif /* META_VIRTUAL_MONITOR_NATIVE_H */ diff --git a/src/backends/native/meta-xkb-utils.c b/src/backends/native/meta-xkb-utils.c deleted file mode 100644 index 45f89bec7..000000000 --- a/src/backends/native/meta-xkb-utils.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2010 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - - * Authors: - * Kristian Høgsberg - * Damien Lespiau <damien.lespiau@intel.com> - */ - -#include "config.h" - -#include "backends/native/meta-xkb-utils.h" -#include "clutter/clutter-keysyms.h" -#include "clutter/clutter-mutter.h" - -/* - * _clutter_event_new_from_evdev: Create a new Clutter ClutterKeyEvent - * @device: a ClutterInputDevice - * @xkb: XKB rules to translate the event - * @_time: timestamp of the event - * @key: a key code coming from a Linux input device - * @state: TRUE if a press event, FALSE if a release event - * @modifer_state: in/out - * - * Translate @key to a #ClutterKeyEvent using rules from xbbcommon. - * - * Return value: the new #ClutterEvent - */ -ClutterEvent * -meta_key_event_new_from_evdev (ClutterInputDevice *device, - ClutterInputDevice *core_device, - struct xkb_state *xkb_state, - uint32_t button_state, - uint32_t _time, - xkb_keycode_t key, - uint32_t state) -{ - ClutterEvent *event; - xkb_keysym_t sym; - const xkb_keysym_t *syms; - char buffer[8]; - int n; - - if (state) - event = clutter_event_new (CLUTTER_KEY_PRESS); - else - event = clutter_event_new (CLUTTER_KEY_RELEASE); - - /* We use a fixed offset of 8 because evdev starts KEY_* numbering from - * 0, whereas X11's minimum keycode, for really stupid reasons, is 8. - * So the evdev XKB rules are based on the keycodes all being shifted - * upwards by 8. */ - key = meta_xkb_evdev_to_keycode (key); - - n = xkb_key_get_syms (xkb_state, key, &syms); - if (n == 1) - sym = syms[0]; - else - sym = XKB_KEY_NoSymbol; - - event->key.time = _time; - meta_xkb_translate_state (event, xkb_state, button_state); - event->key.hardware_keycode = key; - event->key.keyval = sym; - clutter_event_set_device (event, core_device); - clutter_event_set_source_device (event, device); - - n = xkb_keysym_to_utf8 (sym, buffer, sizeof (buffer)); - - if (n == 0) - { - /* not printable */ - event->key.unicode_value = (gunichar) '\0'; - } - else - { - event->key.unicode_value = g_utf8_get_char_validated (buffer, n); - if (event->key.unicode_value == -1 || event->key.unicode_value == -2) - event->key.unicode_value = (gunichar) '\0'; - } - - return event; -} - -void -meta_xkb_translate_state (ClutterEvent *event, - struct xkb_state *state, - uint32_t button_state) -{ - _clutter_event_set_state_full (event, - button_state, - xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED), - xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED), - xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED), - xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE) | button_state); -} - -ClutterModifierType -meta_xkb_translate_modifiers (struct xkb_state *state, - ClutterModifierType button_state) -{ - ClutterModifierType modifiers; - - modifiers = xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE); - modifiers |= button_state; - - return modifiers; -} - -uint32_t -meta_xkb_keycode_to_evdev (uint32_t xkb_keycode) -{ - /* The keycodes from the evdev backend are almost evdev - * keycodes: we use the evdev keycode file, but xkb rules have an - * offset by 8. See the comment in _clutter_key_event_new_from_evdev() - */ - return xkb_keycode - 8; -} - -uint32_t -meta_xkb_evdev_to_keycode (uint32_t evcode) -{ - /* The inverse of meta_xkb_keycode_to_evdev */ - return evcode + 8; -} diff --git a/src/backends/native/meta-xkb-utils.h b/src/backends/native/meta-xkb-utils.h deleted file mode 100644 index d605813e6..000000000 --- a/src/backends/native/meta-xkb-utils.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - - * Authors: - * Damien Lespiau <damien.lespiau@intel.com> - */ - -#ifndef META_XKB_UTILS_H -#define META_XKB_UTILS_H - -#include <xkbcommon/xkbcommon.h> - -#include "clutter/clutter.h" - -ClutterEvent * meta_key_event_new_from_evdev (ClutterInputDevice *device, - ClutterInputDevice *core_keyboard, - struct xkb_state *xkb_state, - uint32_t button_state, - uint32_t _time, - uint32_t key, - uint32_t state); -void meta_xkb_translate_state (ClutterEvent *event, - struct xkb_state *xkb_state, - uint32_t button_state); -ClutterModifierType meta_xkb_translate_modifiers (struct xkb_state *state, - ClutterModifierType button_state); -uint32_t meta_xkb_keycode_to_evdev (uint32_t hardware_keycode); -uint32_t meta_xkb_evdev_to_keycode (uint32_t evcode); - -#endif /* META_XKB_UTILS_H */ |