2014-04-22 15:15:11 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2014 Red Hat
|
2020-02-24 08:36:24 -05:00
|
|
|
* Copyright 2020 DisplayLink (UK) Ltd.
|
2014-04-22 15:15:11 -04:00
|
|
|
*
|
|
|
|
* 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"
|
|
|
|
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "backends/native/meta-cursor-renderer-native.h"
|
2014-04-22 15:15:11 -04:00
|
|
|
|
2015-03-10 23:16:58 -04:00
|
|
|
#include <string.h>
|
2014-04-22 15:15:11 -04:00
|
|
|
#include <gbm.h>
|
2014-09-24 17:40:09 -04:00
|
|
|
#include <xf86drm.h>
|
2015-07-17 11:16:39 -04:00
|
|
|
#include <errno.h>
|
2014-04-22 15:15:11 -04:00
|
|
|
|
2016-05-09 07:51:29 -04:00
|
|
|
#include "backends/meta-backend-private.h"
|
2018-05-02 08:34:02 -04:00
|
|
|
#include "backends/meta-cursor-sprite-xcursor.h"
|
2017-02-24 05:10:52 -05:00
|
|
|
#include "backends/meta-logical-monitor.h"
|
|
|
|
#include "backends/meta-monitor.h"
|
2016-05-09 07:51:29 -04:00
|
|
|
#include "backends/meta-monitor-manager-private.h"
|
2017-03-24 05:35:51 -04:00
|
|
|
#include "backends/meta-output.h"
|
2021-04-12 10:13:29 -04:00
|
|
|
#include "backends/native/meta-backend-native-private.h"
|
2019-11-08 18:19:51 -05:00
|
|
|
#include "backends/native/meta-crtc-kms.h"
|
2021-04-12 10:13:29 -04:00
|
|
|
#include "backends/native/meta-device-pool.h"
|
2020-09-21 13:32:46 -04:00
|
|
|
#include "backends/native/meta-drm-buffer-gbm.h"
|
2019-11-08 18:19:51 -05:00
|
|
|
#include "backends/native/meta-kms-device.h"
|
2020-10-02 10:43:45 -04:00
|
|
|
#include "backends/native/meta-kms-plane.h"
|
2019-11-08 18:19:51 -05:00
|
|
|
#include "backends/native/meta-kms-update.h"
|
|
|
|
#include "backends/native/meta-kms.h"
|
2016-05-09 07:51:29 -04:00
|
|
|
#include "backends/native/meta-renderer-native.h"
|
2017-06-08 10:13:16 -04:00
|
|
|
#include "core/boxes-private.h"
|
2015-07-17 11:16:39 -04:00
|
|
|
#include "meta/boxes.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "meta/meta-backend.h"
|
|
|
|
#include "meta/util.h"
|
2014-04-22 15:15:11 -04:00
|
|
|
|
2018-05-02 06:27:02 -04:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
#include "wayland/meta-cursor-sprite-wayland.h"
|
|
|
|
#include "wayland/meta-wayland-buffer.h"
|
|
|
|
#endif
|
|
|
|
|
2014-09-24 17:40:09 -04:00
|
|
|
#ifndef DRM_CAP_CURSOR_WIDTH
|
|
|
|
#define DRM_CAP_CURSOR_WIDTH 0x8
|
|
|
|
#endif
|
|
|
|
#ifndef DRM_CAP_CURSOR_HEIGHT
|
|
|
|
#define DRM_CAP_CURSOR_HEIGHT 0x9
|
|
|
|
#endif
|
|
|
|
|
2015-07-17 11:16:39 -04:00
|
|
|
/* 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
|
|
|
|
|
2015-03-10 23:16:58 -04:00
|
|
|
static GQuark quark_cursor_sprite = 0;
|
|
|
|
|
2020-10-09 17:57:03 -04:00
|
|
|
typedef struct _CrtcCursorData
|
|
|
|
{
|
|
|
|
MetaDrmBuffer *buffer;
|
2020-10-09 19:02:28 -04:00
|
|
|
gboolean needs_sync_position;
|
|
|
|
gboolean hw_state_invalidated;
|
2020-10-09 17:57:03 -04:00
|
|
|
} CrtcCursorData;
|
|
|
|
|
2017-07-07 04:06:22 -04:00
|
|
|
struct _MetaCursorRendererNative
|
|
|
|
{
|
|
|
|
MetaCursorRenderer parent;
|
|
|
|
};
|
|
|
|
|
2014-04-22 15:15:11 -04:00
|
|
|
struct _MetaCursorRendererNativePrivate
|
|
|
|
{
|
2019-01-11 09:35:42 -05:00
|
|
|
MetaBackend *backend;
|
2017-07-07 04:12:07 -04:00
|
|
|
|
2014-04-22 15:15:11 -04:00
|
|
|
gboolean has_hw_cursor;
|
|
|
|
|
2015-03-09 23:23:00 -04:00
|
|
|
MetaCursorSprite *last_cursor;
|
2015-07-13 14:38:08 -04:00
|
|
|
guint animation_timeout_id;
|
2017-07-24 22:31:25 -04:00
|
|
|
};
|
|
|
|
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
|
2015-07-13 14:38:08 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
typedef struct _MetaCursorRendererNativeGpuData
|
|
|
|
{
|
|
|
|
gboolean hw_cursor_broken;
|
2014-09-24 17:40:09 -04:00
|
|
|
|
|
|
|
uint64_t cursor_width;
|
|
|
|
uint64_t cursor_height;
|
2017-07-24 22:31:25 -04:00
|
|
|
} MetaCursorRendererNativeGpuData;
|
2014-04-22 15:15:11 -04:00
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
typedef enum _MetaCursorBufferState
|
2015-07-17 11:16:39 -04:00
|
|
|
{
|
2020-09-21 13:32:46 -04:00
|
|
|
META_CURSOR_BUFFER_STATE_NONE,
|
|
|
|
META_CURSOR_BUFFER_STATE_SET,
|
|
|
|
META_CURSOR_BUFFER_STATE_INVALIDATED,
|
|
|
|
} MetaCursorBufferState;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
typedef struct _MetaCursorNativeGpuState
|
2015-07-17 11:16:39 -04:00
|
|
|
{
|
2019-02-08 13:33:09 -05:00
|
|
|
MetaGpu *gpu;
|
2020-09-21 13:32:46 -04:00
|
|
|
unsigned int active_buffer_idx;
|
|
|
|
MetaCursorBufferState pending_buffer_state;
|
|
|
|
MetaDrmBuffer *buffers[HW_CURSOR_BUFFER_COUNT];
|
2017-07-24 22:31:25 -04:00
|
|
|
} MetaCursorNativeGpuState;
|
|
|
|
|
|
|
|
typedef struct _MetaCursorNativePrivate
|
|
|
|
{
|
|
|
|
GHashTable *gpu_states;
|
2019-05-13 04:21:40 -04:00
|
|
|
|
|
|
|
struct {
|
|
|
|
gboolean can_preprocess;
|
|
|
|
float current_relative_scale;
|
|
|
|
MetaMonitorTransform current_relative_transform;
|
|
|
|
} preprocess_state;
|
2015-07-17 11:16:39 -04:00
|
|
|
} MetaCursorNativePrivate;
|
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
static GQuark quark_cursor_renderer_native_gpu_data = 0;
|
|
|
|
|
2014-04-22 15:15:11 -04:00
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER);
|
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
static void
|
|
|
|
on_kms_update_result (const MetaKmsFeedback *kms_feedback,
|
|
|
|
gpointer user_data);
|
|
|
|
|
2018-05-02 10:56:53 -04:00
|
|
|
static void
|
|
|
|
realize_cursor_sprite (MetaCursorRenderer *renderer,
|
2018-05-02 14:32:43 -04:00
|
|
|
MetaCursorSprite *cursor_sprite,
|
|
|
|
GList *gpus);
|
2018-05-02 10:56:53 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
static MetaCursorNativeGpuState *
|
|
|
|
get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
|
|
|
|
MetaGpuKms *gpu_kms);
|
|
|
|
|
|
|
|
static MetaCursorNativeGpuState *
|
|
|
|
ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
|
|
|
|
MetaGpuKms *gpu_kms);
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
static void
|
|
|
|
invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite);
|
|
|
|
|
2015-07-17 11:16:39 -04:00
|
|
|
static MetaCursorNativePrivate *
|
|
|
|
ensure_cursor_priv (MetaCursorSprite *cursor_sprite);
|
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-04-22 15:15:11 -04:00
|
|
|
static void
|
|
|
|
meta_cursor_renderer_native_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object);
|
2018-05-02 08:31:44 -04:00
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (renderer);
|
2014-04-22 15:15:11 -04:00
|
|
|
|
2019-11-21 18:25:30 -05:00
|
|
|
g_clear_handle_id (&priv->animation_timeout_id, g_source_remove);
|
2015-07-13 14:38:08 -04:00
|
|
|
|
2014-04-22 15:15:11 -04:00
|
|
|
G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
2020-09-21 13:21:19 -04:00
|
|
|
static unsigned int
|
2020-09-21 13:32:46 -04:00
|
|
|
get_pending_cursor_sprite_buffer_index (MetaCursorNativeGpuState *cursor_gpu_state)
|
2015-07-17 11:16:39 -04:00
|
|
|
{
|
2020-09-21 13:32:46 -04:00
|
|
|
return (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT;
|
2015-07-17 11:16:39 -04:00
|
|
|
}
|
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
static MetaDrmBuffer *
|
|
|
|
get_pending_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state)
|
2015-03-10 23:16:58 -04:00
|
|
|
{
|
2020-09-21 13:32:46 -04:00
|
|
|
unsigned int pending_buffer_idx;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
pending_buffer_idx =
|
|
|
|
get_pending_cursor_sprite_buffer_index (cursor_gpu_state);
|
|
|
|
return cursor_gpu_state->buffers[pending_buffer_idx];
|
2015-03-10 23:16:58 -04:00
|
|
|
}
|
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
static MetaDrmBuffer *
|
|
|
|
get_active_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state)
|
2015-03-10 23:16:58 -04:00
|
|
|
{
|
2020-09-21 13:32:46 -04:00
|
|
|
return cursor_gpu_state->buffers[cursor_gpu_state->active_buffer_idx];
|
2015-03-10 23:16:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-09-21 13:32:46 -04:00
|
|
|
set_pending_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite,
|
2017-07-24 22:31:25 -04:00
|
|
|
MetaGpuKms *gpu_kms,
|
2020-09-21 13:32:46 -04:00
|
|
|
MetaDrmBuffer *buffer)
|
2015-03-10 23:16:58 -04:00
|
|
|
{
|
2015-07-17 11:16:39 -04:00
|
|
|
MetaCursorNativePrivate *cursor_priv;
|
2017-07-24 22:31:25 -04:00
|
|
|
MetaCursorNativeGpuState *cursor_gpu_state;
|
2020-09-21 13:32:46 -04:00
|
|
|
unsigned int pending_buffer_idx;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
|
|
|
cursor_priv = ensure_cursor_priv (cursor_sprite);
|
2017-07-24 22:31:25 -04:00
|
|
|
cursor_gpu_state = ensure_cursor_gpu_state (cursor_priv, gpu_kms);
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
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;
|
2015-03-10 23:16:58 -04:00
|
|
|
}
|
|
|
|
|
2020-03-19 04:06:09 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2020-10-09 17:57:03 -04:00
|
|
|
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);
|
2020-10-09 19:02:28 -04:00
|
|
|
crtc_cursor_data->hw_state_invalidated = TRUE;
|
2020-10-09 17:57:03 -04:00
|
|
|
meta_crtc_kms_set_cursor_renderer_private (crtc_kms,
|
|
|
|
crtc_cursor_data,
|
|
|
|
g_free);
|
|
|
|
}
|
|
|
|
|
|
|
|
return crtc_cursor_data;
|
|
|
|
}
|
|
|
|
|
2014-04-22 15:15:11 -04:00
|
|
|
static void
|
2020-10-09 19:02:28 -04:00
|
|
|
assign_cursor_plane (MetaCursorRendererNative *native,
|
|
|
|
MetaCrtcKms *crtc_kms,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
MetaCursorSprite *cursor_sprite)
|
2014-04-22 15:15:11 -04:00
|
|
|
{
|
2020-02-26 13:47:44 -05:00
|
|
|
MetaCrtc *crtc = META_CRTC (crtc_kms);
|
2019-11-08 18:19:51 -05:00
|
|
|
MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite);
|
|
|
|
MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
|
|
|
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data =
|
2017-07-24 22:31:25 -04:00
|
|
|
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
|
2019-11-08 18:19:51 -05:00
|
|
|
MetaCursorNativeGpuState *cursor_gpu_state =
|
|
|
|
get_cursor_gpu_state (cursor_priv, gpu_kms);
|
|
|
|
MetaKmsCrtc *kms_crtc;
|
|
|
|
MetaKmsDevice *kms_device;
|
|
|
|
MetaKmsPlane *cursor_plane;
|
2020-09-21 13:32:46 -04:00
|
|
|
MetaDrmBuffer *buffer;
|
2019-11-08 18:19:51 -05:00
|
|
|
int cursor_width, cursor_height;
|
|
|
|
MetaFixed16Rectangle src_rect;
|
2020-09-21 12:00:36 -04:00
|
|
|
MetaRectangle dst_rect;
|
2020-09-21 13:32:46 -04:00
|
|
|
MetaDrmBuffer *crtc_buffer;
|
2019-11-08 18:19:51 -05:00
|
|
|
MetaKmsAssignPlaneFlag flags;
|
2020-10-09 17:57:03 -04:00
|
|
|
CrtcCursorData *crtc_cursor_data;
|
2020-03-19 04:06:09 -04:00
|
|
|
int cursor_hotspot_x;
|
|
|
|
int cursor_hotspot_y;
|
2020-10-09 19:02:28 -04:00
|
|
|
MetaKmsUpdate *kms_update;
|
2020-03-19 04:06:09 -04:00
|
|
|
MetaKmsPlaneAssignment *plane_assignment;
|
2019-11-08 18:19:51 -05:00
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET)
|
|
|
|
buffer = get_pending_cursor_sprite_buffer (cursor_gpu_state);
|
2019-11-08 18:19:51 -05:00
|
|
|
else
|
2020-09-21 13:32:46 -04:00
|
|
|
buffer = get_active_cursor_sprite_buffer (cursor_gpu_state);
|
2019-11-08 18:19:51 -05:00
|
|
|
|
2020-02-26 13:47:44 -05:00
|
|
|
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
2019-11-08 18:19:51 -05:00
|
|
|
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),
|
|
|
|
};
|
2020-09-21 12:00:36 -04:00
|
|
|
dst_rect = (MetaRectangle) {
|
|
|
|
.x = x,
|
|
|
|
.y = y,
|
|
|
|
.width = cursor_width,
|
|
|
|
.height = cursor_height,
|
2019-11-08 18:19:51 -05:00
|
|
|
};
|
2014-04-22 15:15:11 -04:00
|
|
|
|
2020-10-02 09:45:28 -04:00
|
|
|
flags = META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL;
|
2020-10-09 17:57:03 -04:00
|
|
|
crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms);
|
|
|
|
crtc_buffer = crtc_cursor_data->buffer;
|
2020-10-09 19:02:28 -04:00
|
|
|
if (!crtc_cursor_data->hw_state_invalidated && buffer == crtc_buffer)
|
2019-11-08 18:19:51 -05:00
|
|
|
flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED;
|
2014-04-22 15:15:11 -04:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
kms_update =
|
|
|
|
meta_kms_ensure_pending_update (meta_kms_device_get_kms (kms_device),
|
|
|
|
meta_kms_crtc_get_device (kms_crtc));
|
2020-03-19 04:06:09 -04:00
|
|
|
plane_assignment = meta_kms_update_assign_plane (kms_update,
|
|
|
|
kms_crtc,
|
|
|
|
cursor_plane,
|
2020-09-21 13:32:46 -04:00
|
|
|
buffer,
|
2020-03-19 04:06:09 -04:00
|
|
|
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);
|
2017-07-24 22:31:25 -04:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
meta_kms_update_add_result_listener (kms_update,
|
|
|
|
on_kms_update_result,
|
|
|
|
native);
|
|
|
|
|
2020-10-09 17:57:03 -04:00
|
|
|
crtc_cursor_data->buffer = buffer;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET)
|
2019-11-08 18:19:51 -05:00
|
|
|
{
|
2020-09-21 13:32:46 -04:00
|
|
|
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;
|
2019-11-08 18:19:51 -05:00
|
|
|
}
|
|
|
|
}
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
static void
|
|
|
|
set_crtc_cursor (MetaCursorRendererNative *cursor_renderer_native,
|
|
|
|
MetaRendererView *view,
|
|
|
|
MetaCrtc *crtc,
|
|
|
|
MetaCursorSprite *cursor_sprite)
|
2017-02-24 05:10:52 -05:00
|
|
|
{
|
2020-10-09 19:02:28 -04:00
|
|
|
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;
|
2018-03-26 09:56:04 -04:00
|
|
|
MetaMonitorTransform transform;
|
2020-10-09 19:02:28 -04:00
|
|
|
MetaMonitorTransform inverted_transform;
|
|
|
|
MetaMonitorMode *monitor_mode;
|
|
|
|
MetaMonitorCrtcMode *monitor_crtc_mode;
|
2020-02-26 18:08:58 -05:00
|
|
|
const MetaCrtcModeInfo *crtc_mode_info;
|
2017-02-24 05:10:52 -05:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view));
|
2017-02-24 05:10:52 -05:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
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);
|
2020-04-14 15:14:24 -04:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
local_crtc_rect = crtc_config->layout;
|
|
|
|
graphene_rect_offset (&local_crtc_rect,
|
|
|
|
-logical_monitor->rect.x,
|
|
|
|
-logical_monitor->rect.y);
|
2020-02-26 18:08:58 -05:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
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;
|
2018-03-26 09:56:04 -04:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
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)
|
2017-02-24 05:10:52 -05:00
|
|
|
};
|
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
transform = meta_logical_monitor_get_transform (logical_monitor);
|
|
|
|
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
|
2017-11-03 06:25:30 -04:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
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,
|
2020-02-26 13:47:44 -05:00
|
|
|
META_CRTC_KMS (crtc),
|
2019-05-13 04:21:40 -04:00
|
|
|
cursor_rect.x,
|
|
|
|
cursor_rect.y,
|
2020-10-09 19:02:28 -04:00
|
|
|
cursor_sprite);
|
|
|
|
}
|
2017-02-24 05:10:52 -05:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
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)
|
2017-02-24 05:10:52 -05:00
|
|
|
{
|
2020-10-09 19:02:28 -04:00
|
|
|
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);
|
2017-02-24 05:10:52 -05:00
|
|
|
}
|
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
crtc_cursor_data->buffer = NULL;
|
2017-02-24 05:10:52 -05:00
|
|
|
}
|
|
|
|
|
2019-11-08 18:19:51 -05:00
|
|
|
static void
|
|
|
|
disable_hw_cursor_for_crtc (MetaKmsCrtc *kms_crtc,
|
|
|
|
const GError *error)
|
|
|
|
{
|
2020-02-26 13:47:44 -05:00
|
|
|
MetaCrtcKms *crtc_kms = meta_crtc_kms_from_kms_crtc (kms_crtc);
|
|
|
|
MetaCrtc *crtc = META_CRTC (crtc_kms);
|
2019-11-08 18:19:51 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
void
|
|
|
|
meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native,
|
|
|
|
MetaRendererView *view)
|
2014-04-22 15:15:11 -04:00
|
|
|
{
|
2020-10-09 19:02:28 -04:00
|
|
|
MetaCursorRenderer *cursor_renderer =
|
|
|
|
META_CURSOR_RENDERER (cursor_renderer_native);
|
2018-05-02 08:31:44 -04:00
|
|
|
MetaCursorRendererNativePrivate *priv =
|
2020-10-09 19:02:28 -04:00
|
|
|
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
|
2019-01-11 09:35:42 -05:00
|
|
|
MetaBackend *backend = priv->backend;
|
|
|
|
MetaMonitorManager *monitor_manager =
|
|
|
|
meta_backend_get_monitor_manager (backend);
|
2020-10-09 19:02:28 -04:00
|
|
|
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;
|
2019-11-08 18:19:51 -05:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
if (meta_monitor_manager_get_power_save_mode (monitor_manager) !=
|
|
|
|
META_POWER_SAVE_ON)
|
|
|
|
return;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
Introduce virtual monitors
Virtual monitors are monitors that isn't backed by any monitor like
hardware. It would typically be backed by e.g. a remote desktop service,
or a network display.
It is currently only supported by the native backend, and whether the
X11 backend will ever see virtual monitors is an open question. This
rest of this commit message describes how it works under the native
backend.
Each virutal monitor consists of virtualized mode setting components:
* A virtual CRTC mode (MetaCrtcModeVirtual)
* A virtual CRTC (MetaCrtcVirtual)
* A virtual connector (MetaOutputVirtual)
In difference to the corresponding mode setting objects that represents
KMS objects, the virtual ones isn't directly tied to a MetaGpu, other
than the CoglFramebuffer being part of the GPU context of the primary
GPU, which is the case for all monitors no matter what GPU they are
connected to. Part of the reason for this is that a MetaGpu in practice
represents a mode setting device, and its CRTCs and outputs, are all
backed by real mode setting objects, while a virtual monitor is only
backed by a framebuffer that is tied to the primary GPU. Maybe this will
be reevaluated in the future, but since a virtual monitor is not tied to
any GPU currently, so is the case for the virtual mode setting objects.
The native rendering backend, including the cursor renderer, is adapted
to handle the situation where a CRTC does not have a GPU associated with
it; this in practice means that it e.g. will not try to upload HW cursor
buffers when the cursor is only on a virtual monitor. The same applies
to the native renderer, which is made to avoid creating
MetaOnscreenNative for views that are backed by virtual CRTCs, as well
as to avoid trying to mode set on such views.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1698>
2021-01-26 10:49:28 -05:00
|
|
|
if (!meta_crtc_get_gpu (crtc))
|
|
|
|
return;
|
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
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;
|
2017-02-24 05:10:52 -05:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
|
|
|
|
if (!cursor_sprite)
|
|
|
|
goto unset_cursor;
|
2017-02-24 05:10:52 -05:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
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;
|
2016-01-10 11:28:54 -05:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
set_crtc_cursor (cursor_renderer_native, view, crtc, cursor_sprite);
|
2017-01-10 03:01:46 -05:00
|
|
|
|
2021-02-02 08:49:56 -05:00
|
|
|
meta_cursor_renderer_emit_painted (cursor_renderer,
|
|
|
|
cursor_sprite,
|
|
|
|
CLUTTER_STAGE_VIEW (view));
|
2020-10-09 19:02:28 -04:00
|
|
|
|
|
|
|
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;
|
2014-04-22 15:15:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2020-09-21 13:32:46 -04:00
|
|
|
has_valid_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite,
|
2017-07-24 22:31:25 -04:00
|
|
|
MetaGpuKms *gpu_kms)
|
2014-04-22 15:15:11 -04:00
|
|
|
{
|
2017-07-24 22:31:25 -04:00
|
|
|
MetaCursorNativePrivate *cursor_priv;
|
|
|
|
MetaCursorNativeGpuState *cursor_gpu_state;
|
2014-04-22 15:15:11 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
cursor_priv = get_cursor_priv (cursor_sprite);
|
2016-01-08 10:09:10 -05:00
|
|
|
if (!cursor_priv)
|
|
|
|
return FALSE;
|
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);
|
|
|
|
if (!cursor_gpu_state)
|
|
|
|
return FALSE;
|
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
switch (cursor_gpu_state->pending_buffer_state)
|
2015-07-17 11:16:39 -04:00
|
|
|
{
|
2020-09-21 13:32:46 -04:00
|
|
|
case META_CURSOR_BUFFER_STATE_NONE:
|
|
|
|
return get_active_cursor_sprite_buffer (cursor_gpu_state) != NULL;
|
|
|
|
case META_CURSOR_BUFFER_STATE_SET:
|
2015-07-17 11:16:39 -04:00
|
|
|
return TRUE;
|
2020-09-21 13:32:46 -04:00
|
|
|
case META_CURSOR_BUFFER_STATE_INVALIDATED:
|
2015-07-17 11:16:39 -04:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-12-18 06:16:59 -05:00
|
|
|
static gboolean
|
2019-05-13 04:21:40 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-02-21 06:08:34 -05:00
|
|
|
static void
|
|
|
|
has_cursor_plane (MetaLogicalMonitor *logical_monitor,
|
|
|
|
MetaMonitor *monitor,
|
|
|
|
MetaOutput *output,
|
|
|
|
MetaCrtc *crtc,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
gboolean *has_cursor_planes = user_data;
|
2020-02-26 13:47:44 -05:00
|
|
|
MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc);
|
|
|
|
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
2020-02-21 06:08:34 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
static gboolean
|
|
|
|
get_common_crtc_sprite_scale_for_logical_monitors (MetaCursorRenderer *renderer,
|
|
|
|
MetaCursorSprite *cursor_sprite,
|
|
|
|
float *out_scale)
|
2015-12-18 06:16:59 -05:00
|
|
|
{
|
2017-07-07 04:12:07 -04:00
|
|
|
MetaCursorRendererNative *cursor_renderer_native =
|
|
|
|
META_CURSOR_RENDERER_NATIVE (renderer);
|
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
|
2019-01-11 09:35:42 -05:00
|
|
|
MetaBackend *backend = priv->backend;
|
|
|
|
MetaMonitorManager *monitor_manager =
|
|
|
|
meta_backend_get_monitor_manager (backend);
|
2019-05-13 04:21:40 -04:00
|
|
|
graphene_rect_t cursor_rect;
|
|
|
|
float scale = 1.0;
|
|
|
|
gboolean has_visible_crtc_sprite = FALSE;
|
2017-08-11 03:02:43 -04:00
|
|
|
GList *logical_monitors;
|
|
|
|
GList *l;
|
2015-12-18 06:16:59 -05:00
|
|
|
|
2017-08-11 03:02:43 -04:00
|
|
|
cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
|
2017-07-24 22:31:25 -04:00
|
|
|
|
2017-08-11 03:02:43 -04:00
|
|
|
logical_monitors =
|
|
|
|
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
2019-05-13 04:21:40 -04:00
|
|
|
|
2017-08-11 03:02:43 -04:00
|
|
|
for (l = logical_monitors; l; l = l->next)
|
2015-12-18 06:16:59 -05:00
|
|
|
{
|
2017-08-11 03:02:43 -04:00
|
|
|
MetaLogicalMonitor *logical_monitor = l->data;
|
2019-05-13 04:21:40 -04:00
|
|
|
graphene_rect_t logical_monitor_rect =
|
|
|
|
meta_rectangle_to_graphene_rect (&logical_monitor->rect);
|
|
|
|
float tmp_scale;
|
2017-06-08 10:13:16 -04:00
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
if (!graphene_rect_intersection (&cursor_rect,
|
|
|
|
&logical_monitor_rect,
|
2019-02-20 10:23:04 -05:00
|
|
|
NULL))
|
2015-12-18 06:16:59 -05:00
|
|
|
continue;
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
tmp_scale =
|
|
|
|
calculate_cursor_crtc_sprite_scale (cursor_sprite, logical_monitor);
|
2017-10-06 08:48:32 -04:00
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
if (has_visible_crtc_sprite && scale != tmp_scale)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
has_visible_crtc_sprite = TRUE;
|
|
|
|
scale = tmp_scale;
|
2015-12-18 06:16:59 -05:00
|
|
|
}
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
if (!has_visible_crtc_sprite)
|
|
|
|
return FALSE;
|
2015-12-18 06:16:59 -05:00
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
*out_scale = scale;
|
|
|
|
return TRUE;
|
2017-02-24 05:10:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2019-05-13 04:21:40 -04:00
|
|
|
get_common_crtc_sprite_transform_for_logical_monitors (MetaCursorRenderer *renderer,
|
|
|
|
MetaCursorSprite *cursor_sprite,
|
|
|
|
MetaMonitorTransform *out_transform)
|
2017-02-24 05:10:52 -05:00
|
|
|
{
|
2017-07-07 04:12:07 -04:00
|
|
|
MetaCursorRendererNative *cursor_renderer_native =
|
|
|
|
META_CURSOR_RENDERER_NATIVE (renderer);
|
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
|
2019-01-11 09:35:42 -05:00
|
|
|
MetaBackend *backend = priv->backend;
|
|
|
|
MetaMonitorManager *monitor_manager =
|
|
|
|
meta_backend_get_monitor_manager (backend);
|
2019-02-20 10:23:04 -05:00
|
|
|
graphene_rect_t cursor_rect;
|
2019-05-13 04:21:40 -04:00
|
|
|
MetaMonitorTransform transform = META_MONITOR_TRANSFORM_NORMAL;
|
|
|
|
gboolean has_visible_crtc_sprite = FALSE;
|
2017-02-24 05:10:52 -05:00
|
|
|
GList *logical_monitors;
|
|
|
|
GList *l;
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
|
2017-02-24 05:10:52 -05:00
|
|
|
|
|
|
|
logical_monitors =
|
|
|
|
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
|
|
|
|
|
|
|
for (l = logical_monitors; l; l = l->next)
|
|
|
|
{
|
|
|
|
MetaLogicalMonitor *logical_monitor = l->data;
|
2019-02-20 10:23:04 -05:00
|
|
|
graphene_rect_t logical_monitor_rect =
|
|
|
|
meta_rectangle_to_graphene_rect (&logical_monitor->rect);
|
2020-03-27 09:57:27 -04:00
|
|
|
MetaMonitorTransform logical_transform, tmp_transform;
|
|
|
|
GList *monitors, *l_mon;
|
2017-02-24 05:10:52 -05:00
|
|
|
|
2019-02-20 10:23:04 -05:00
|
|
|
if (!graphene_rect_intersection (&cursor_rect,
|
|
|
|
&logical_monitor_rect,
|
|
|
|
NULL))
|
2017-02-24 05:10:52 -05:00
|
|
|
continue;
|
|
|
|
|
2020-03-27 09:57:27 -04:00
|
|
|
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;
|
2019-05-13 04:21:40 -04:00
|
|
|
|
2020-03-27 09:57:27 -04:00
|
|
|
tmp_transform = meta_monitor_transform_relative_transform (
|
|
|
|
meta_cursor_sprite_get_texture_transform (cursor_sprite),
|
|
|
|
meta_monitor_logical_to_crtc_transform (monitor, logical_transform));
|
2017-02-24 05:10:52 -05:00
|
|
|
|
2020-03-27 09:57:27 -04:00
|
|
|
if (has_visible_crtc_sprite && transform != tmp_transform)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
has_visible_crtc_sprite = TRUE;
|
|
|
|
transform = tmp_transform;
|
|
|
|
}
|
2017-02-24 05:10:52 -05:00
|
|
|
}
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
if (!has_visible_crtc_sprite)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
*out_transform = transform;
|
|
|
|
return TRUE;
|
2017-02-24 05:10:52 -05:00
|
|
|
}
|
|
|
|
|
2015-07-17 11:16:39 -04:00
|
|
|
static gboolean
|
|
|
|
should_have_hw_cursor (MetaCursorRenderer *renderer,
|
2018-05-02 14:32:43 -04:00
|
|
|
MetaCursorSprite *cursor_sprite,
|
|
|
|
GList *gpus)
|
2015-07-17 11:16:39 -04:00
|
|
|
{
|
2020-07-13 11:45:41 -04:00
|
|
|
MetaCursorRendererNative *cursor_renderer_native =
|
|
|
|
META_CURSOR_RENDERER_NATIVE (renderer);
|
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
|
2015-07-17 11:16:39 -04:00
|
|
|
CoglTexture *texture;
|
2019-05-13 04:21:40 -04:00
|
|
|
MetaMonitorTransform transform;
|
|
|
|
float scale;
|
|
|
|
GList *l;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
Introduce virtual monitors
Virtual monitors are monitors that isn't backed by any monitor like
hardware. It would typically be backed by e.g. a remote desktop service,
or a network display.
It is currently only supported by the native backend, and whether the
X11 backend will ever see virtual monitors is an open question. This
rest of this commit message describes how it works under the native
backend.
Each virutal monitor consists of virtualized mode setting components:
* A virtual CRTC mode (MetaCrtcModeVirtual)
* A virtual CRTC (MetaCrtcVirtual)
* A virtual connector (MetaOutputVirtual)
In difference to the corresponding mode setting objects that represents
KMS objects, the virtual ones isn't directly tied to a MetaGpu, other
than the CoglFramebuffer being part of the GPU context of the primary
GPU, which is the case for all monitors no matter what GPU they are
connected to. Part of the reason for this is that a MetaGpu in practice
represents a mode setting device, and its CRTCs and outputs, are all
backed by real mode setting objects, while a virtual monitor is only
backed by a framebuffer that is tied to the primary GPU. Maybe this will
be reevaluated in the future, but since a virtual monitor is not tied to
any GPU currently, so is the case for the virtual mode setting objects.
The native rendering backend, including the cursor renderer, is adapted
to handle the situation where a CRTC does not have a GPU associated with
it; this in practice means that it e.g. will not try to upload HW cursor
buffers when the cursor is only on a virtual monitor. The same applies
to the native renderer, which is made to avoid creating
MetaOnscreenNative for views that are backed by virtual CRTCs, as well
as to avoid trying to mode set on such views.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1698>
2021-01-26 10:49:28 -05:00
|
|
|
if (!gpus)
|
|
|
|
return FALSE;
|
|
|
|
|
2015-07-17 11:16:39 -04:00
|
|
|
if (!cursor_sprite)
|
2014-04-22 15:15:11 -04:00
|
|
|
return FALSE;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2020-07-13 11:45:41 -04:00
|
|
|
if (meta_backend_is_hw_cursors_inhibited (priv->backend))
|
2018-09-13 05:28:51 -04:00
|
|
|
return FALSE;
|
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
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;
|
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
if (!has_valid_cursor_sprite_buffer (cursor_sprite, gpu_kms))
|
2017-07-24 22:31:25 -04:00
|
|
|
return FALSE;
|
|
|
|
}
|
2017-07-10 06:19:32 -04:00
|
|
|
|
2020-02-21 06:08:34 -05:00
|
|
|
if (!crtcs_has_cursor_planes (renderer, cursor_sprite))
|
|
|
|
return FALSE;
|
|
|
|
|
2015-07-17 11:16:39 -04:00
|
|
|
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
|
|
|
|
if (!texture)
|
|
|
|
return FALSE;
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
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))
|
2015-07-17 11:16:39 -04:00
|
|
|
return FALSE;
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
if (G_APPROX_VALUE (scale, 1.f, FLT_EPSILON) &&
|
|
|
|
transform == META_MONITOR_TRANSFORM_NORMAL)
|
|
|
|
return TRUE;
|
|
|
|
else
|
|
|
|
return get_can_preprocess (cursor_sprite);
|
|
|
|
|
2015-07-17 11:16:39 -04:00
|
|
|
return TRUE;
|
2014-04-22 15:15:11 -04:00
|
|
|
}
|
|
|
|
|
2015-07-13 14:38:08 -04:00
|
|
|
static gboolean
|
|
|
|
meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native)
|
|
|
|
{
|
2018-05-02 08:31:44 -04:00
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (native);
|
2015-07-17 11:16:39 -04:00
|
|
|
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
|
|
|
|
MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer);
|
2015-07-13 14:38:08 -04:00
|
|
|
|
|
|
|
priv->animation_timeout_id = 0;
|
2015-03-09 23:23:00 -04:00
|
|
|
meta_cursor_sprite_tick_frame (cursor_sprite);
|
2015-07-17 11:16:39 -04:00
|
|
|
meta_cursor_renderer_force_update (renderer);
|
2015-07-13 14:38:08 -04:00
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-05-02 10:43:30 -04:00
|
|
|
maybe_schedule_cursor_sprite_animation_frame (MetaCursorRendererNative *native,
|
|
|
|
MetaCursorSprite *cursor_sprite)
|
2015-07-13 14:38:08 -04:00
|
|
|
{
|
2018-05-02 08:31:44 -04:00
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (native);
|
2015-07-13 14:38:08 -04:00
|
|
|
gboolean cursor_change;
|
|
|
|
guint delay;
|
|
|
|
|
2015-03-09 23:23:00 -04:00
|
|
|
cursor_change = cursor_sprite != priv->last_cursor;
|
|
|
|
priv->last_cursor = cursor_sprite;
|
2015-07-13 14:38:08 -04:00
|
|
|
|
|
|
|
if (!cursor_change && priv->animation_timeout_id)
|
|
|
|
return;
|
|
|
|
|
2019-11-21 18:25:30 -05:00
|
|
|
g_clear_handle_id (&priv->animation_timeout_id, g_source_remove);
|
2015-07-13 14:38:08 -04:00
|
|
|
|
2015-03-09 23:23:00 -04:00
|
|
|
if (cursor_sprite && meta_cursor_sprite_is_animated (cursor_sprite))
|
2015-07-13 14:38:08 -04:00
|
|
|
{
|
2015-03-09 23:23:00 -04:00
|
|
|
delay = meta_cursor_sprite_get_current_frame_time (cursor_sprite);
|
2015-07-13 14:38:08 -04:00
|
|
|
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-02 14:32:43 -04:00
|
|
|
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);
|
2019-01-11 09:35:42 -05:00
|
|
|
MetaBackend *backend = priv->backend;
|
|
|
|
MetaMonitorManager *monitor_manager =
|
|
|
|
meta_backend_get_monitor_manager (backend);
|
2018-05-02 14:32:43 -04:00
|
|
|
GList *gpus = NULL;
|
|
|
|
GList *logical_monitors;
|
|
|
|
GList *l;
|
2019-02-20 10:23:04 -05:00
|
|
|
graphene_rect_t cursor_rect;
|
2018-05-02 14:32:43 -04:00
|
|
|
|
|
|
|
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;
|
2019-02-20 10:23:04 -05:00
|
|
|
graphene_rect_t logical_monitor_rect;
|
2018-05-02 14:32:43 -04:00
|
|
|
GList *monitors, *l_mon;
|
|
|
|
|
|
|
|
logical_monitor_layout =
|
|
|
|
meta_logical_monitor_get_layout (logical_monitor);
|
|
|
|
logical_monitor_rect =
|
2019-02-20 10:23:04 -05:00
|
|
|
meta_rectangle_to_graphene_rect (&logical_monitor_layout);
|
2018-05-02 14:32:43 -04:00
|
|
|
|
2019-02-20 10:23:04 -05:00
|
|
|
if (!graphene_rect_intersection (&cursor_rect, &logical_monitor_rect,
|
|
|
|
NULL))
|
2018-05-02 14:32:43 -04:00
|
|
|
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;
|
2021-01-26 08:49:25 -05:00
|
|
|
MetaOutput *output = meta_monitor_get_main_output (monitor);
|
2018-05-02 14:32:43 -04:00
|
|
|
MetaGpu *gpu;
|
|
|
|
|
2021-01-26 08:49:25 -05:00
|
|
|
gpu = meta_output_get_gpu (output);
|
Introduce virtual monitors
Virtual monitors are monitors that isn't backed by any monitor like
hardware. It would typically be backed by e.g. a remote desktop service,
or a network display.
It is currently only supported by the native backend, and whether the
X11 backend will ever see virtual monitors is an open question. This
rest of this commit message describes how it works under the native
backend.
Each virutal monitor consists of virtualized mode setting components:
* A virtual CRTC mode (MetaCrtcModeVirtual)
* A virtual CRTC (MetaCrtcVirtual)
* A virtual connector (MetaOutputVirtual)
In difference to the corresponding mode setting objects that represents
KMS objects, the virtual ones isn't directly tied to a MetaGpu, other
than the CoglFramebuffer being part of the GPU context of the primary
GPU, which is the case for all monitors no matter what GPU they are
connected to. Part of the reason for this is that a MetaGpu in practice
represents a mode setting device, and its CRTCs and outputs, are all
backed by real mode setting objects, while a virtual monitor is only
backed by a framebuffer that is tied to the primary GPU. Maybe this will
be reevaluated in the future, but since a virtual monitor is not tied to
any GPU currently, so is the case for the virtual mode setting objects.
The native rendering backend, including the cursor renderer, is adapted
to handle the situation where a CRTC does not have a GPU associated with
it; this in practice means that it e.g. will not try to upload HW cursor
buffers when the cursor is only on a virtual monitor. The same applies
to the native renderer, which is made to avoid creating
MetaOnscreenNative for views that are backed by virtual CRTCs, as well
as to avoid trying to mode set on such views.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1698>
2021-01-26 10:49:28 -05:00
|
|
|
if (gpu && !g_list_find (gpus, gpu))
|
2018-05-02 14:32:43 -04:00
|
|
|
gpus = g_list_prepend (gpus, gpu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return gpus;
|
|
|
|
}
|
|
|
|
|
2020-10-02 10:43:45 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-17 11:22:05 -04:00
|
|
|
static gboolean
|
2015-07-17 11:16:39 -04:00
|
|
|
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
|
|
|
|
MetaCursorSprite *cursor_sprite)
|
2014-04-22 15:15:11 -04:00
|
|
|
{
|
|
|
|
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
2018-05-02 08:31:44 -04:00
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (native);
|
2020-10-09 19:02:28 -04:00
|
|
|
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (priv->backend));
|
2018-05-02 14:32:43 -04:00
|
|
|
g_autoptr (GList) gpus = NULL;
|
2014-04-22 15:15:11 -04:00
|
|
|
|
2015-07-17 11:16:39 -04:00
|
|
|
if (cursor_sprite)
|
2018-05-02 14:32:43 -04:00
|
|
|
{
|
|
|
|
meta_cursor_sprite_realize_texture (cursor_sprite);
|
|
|
|
gpus = calculate_cursor_sprite_gpus (renderer, cursor_sprite);
|
|
|
|
realize_cursor_sprite (renderer, cursor_sprite, gpus);
|
|
|
|
}
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2018-05-02 10:43:30 -04:00
|
|
|
maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite);
|
2015-07-13 14:38:08 -04:00
|
|
|
|
2018-05-02 14:32:43 -04:00
|
|
|
priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite, gpus);
|
2020-10-02 10:43:45 -04:00
|
|
|
|
2020-10-09 19:02:28 -04:00
|
|
|
schedule_sync_position (native);
|
|
|
|
clutter_stage_schedule_update (stage);
|
2020-10-02 10:43:45 -04:00
|
|
|
|
2018-05-11 07:23:39 -04:00
|
|
|
return (priv->has_hw_cursor ||
|
|
|
|
!cursor_sprite ||
|
|
|
|
!meta_cursor_sprite_get_cogl_texture (cursor_sprite));
|
2014-04-22 15:15:11 -04:00
|
|
|
}
|
|
|
|
|
2019-02-08 13:33:09 -05:00
|
|
|
static void
|
|
|
|
unset_crtc_cursor_renderer_privates (MetaGpu *gpu,
|
2020-09-21 13:32:46 -04:00
|
|
|
MetaDrmBuffer *buffer)
|
2019-02-08 13:33:09 -05:00
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
|
|
|
|
{
|
2020-02-26 13:47:44 -05:00
|
|
|
MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data);
|
2020-09-21 13:32:46 -04:00
|
|
|
MetaDrmBuffer *crtc_buffer;
|
2019-02-08 13:33:09 -05:00
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
crtc_buffer = meta_crtc_kms_get_cursor_renderer_private (crtc_kms);
|
|
|
|
if (buffer == crtc_buffer)
|
2020-10-09 17:57:03 -04:00
|
|
|
meta_crtc_kms_set_cursor_renderer_private (crtc_kms, NULL, NULL);
|
2019-02-08 13:33:09 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-10 23:16:58 -04:00
|
|
|
static void
|
2017-07-24 22:31:25 -04:00
|
|
|
cursor_gpu_state_free (MetaCursorNativeGpuState *cursor_gpu_state)
|
2015-03-10 23:16:58 -04:00
|
|
|
{
|
2017-07-24 22:31:25 -04:00
|
|
|
int i;
|
2020-09-21 13:32:46 -04:00
|
|
|
MetaDrmBuffer *active_buffer;
|
2019-02-08 13:33:09 -05:00
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
active_buffer = get_active_cursor_sprite_buffer (cursor_gpu_state);
|
|
|
|
if (active_buffer)
|
|
|
|
unset_crtc_cursor_renderer_privates (cursor_gpu_state->gpu,
|
|
|
|
active_buffer);
|
2015-03-10 23:16:58 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++)
|
2020-09-21 13:32:46 -04:00
|
|
|
g_clear_object (&cursor_gpu_state->buffers[i]);
|
2017-07-24 22:31:25 -04:00
|
|
|
g_free (cursor_gpu_state);
|
2015-03-10 23:16:58 -04:00
|
|
|
}
|
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
static MetaCursorNativeGpuState *
|
|
|
|
get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
|
|
|
|
MetaGpuKms *gpu_kms)
|
2015-07-17 11:16:39 -04:00
|
|
|
{
|
2017-07-24 22:31:25 -04:00
|
|
|
return g_hash_table_lookup (cursor_priv->gpu_states, gpu_kms);
|
|
|
|
}
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
static MetaCursorNativeGpuState *
|
|
|
|
ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
|
|
|
|
MetaGpuKms *gpu_kms)
|
|
|
|
{
|
|
|
|
MetaCursorNativeGpuState *cursor_gpu_state;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
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);
|
2019-02-08 13:33:09 -05:00
|
|
|
cursor_gpu_state->gpu = META_GPU (gpu_kms);
|
2017-07-24 22:31:25 -04:00
|
|
|
g_hash_table_insert (cursor_priv->gpu_states, gpu_kms, cursor_gpu_state);
|
|
|
|
|
|
|
|
return cursor_gpu_state;
|
|
|
|
}
|
|
|
|
|
2018-05-02 10:56:53 -04:00
|
|
|
static void
|
2019-05-13 04:21:40 -04:00
|
|
|
invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite)
|
2018-05-02 10:56:53 -04:00
|
|
|
{
|
|
|
|
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))
|
|
|
|
{
|
2020-09-21 13:32:46 -04:00
|
|
|
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;
|
2018-05-02 10:56:53 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
static void
|
|
|
|
on_cursor_sprite_texture_changed (MetaCursorSprite *cursor_sprite)
|
|
|
|
{
|
|
|
|
invalidate_cursor_gpu_state (cursor_sprite);
|
|
|
|
}
|
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
static void
|
|
|
|
cursor_priv_free (MetaCursorNativePrivate *cursor_priv)
|
|
|
|
{
|
|
|
|
g_hash_table_destroy (cursor_priv->gpu_states);
|
2019-05-17 15:46:33 -04:00
|
|
|
g_free (cursor_priv);
|
2017-07-24 22:31:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static MetaCursorNativePrivate *
|
|
|
|
get_cursor_priv (MetaCursorSprite *cursor_sprite)
|
|
|
|
{
|
|
|
|
return g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
|
2015-07-17 11:16:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static MetaCursorNativePrivate *
|
|
|
|
ensure_cursor_priv (MetaCursorSprite *cursor_sprite)
|
|
|
|
{
|
2017-07-24 22:31:25 -04:00
|
|
|
MetaCursorNativePrivate *cursor_priv;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
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);
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2018-05-02 10:56:53 -04:00
|
|
|
g_signal_connect (cursor_sprite, "texture-changed",
|
|
|
|
G_CALLBACK (on_cursor_sprite_texture_changed), NULL);
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
unset_can_preprocess (cursor_sprite);
|
|
|
|
|
2015-07-17 11:16:39 -04:00
|
|
|
return cursor_priv;
|
|
|
|
}
|
|
|
|
|
2015-03-10 23:16:58 -04:00
|
|
|
static void
|
2017-07-24 22:31:25 -04:00
|
|
|
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)
|
2015-03-10 23:16:58 -04:00
|
|
|
{
|
2021-04-12 10:13:29 -04:00
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (native);
|
2015-03-10 23:16:58 -04:00
|
|
|
uint64_t cursor_width, cursor_height;
|
2017-07-24 22:31:25 -04:00
|
|
|
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;
|
2015-03-10 23:16:58 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width;
|
|
|
|
cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height;
|
2015-03-10 23:16:58 -04:00
|
|
|
|
|
|
|
if (width > cursor_width || height > cursor_height)
|
|
|
|
{
|
2020-10-02 11:47:22 -04:00
|
|
|
meta_warning ("Invalid theme cursor size (must be at most %ux%u)",
|
2015-03-10 23:16:58 -04:00
|
|
|
(unsigned int)cursor_width, (unsigned int)cursor_height);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
gbm_device = meta_gbm_device_from_gpu (gpu_kms);
|
|
|
|
if (gbm_device_is_format_supported (gbm_device, gbm_format,
|
2015-03-10 23:16:58 -04:00
|
|
|
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
|
|
|
|
{
|
2021-04-12 10:13:29 -04:00
|
|
|
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;
|
2015-03-10 23:16:58 -04:00
|
|
|
struct gbm_bo *bo;
|
|
|
|
uint8_t buf[4 * cursor_width * cursor_height];
|
|
|
|
uint i;
|
2020-09-21 13:32:46 -04:00
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
MetaDrmBufferGbm *buffer_gbm;
|
2015-03-10 23:16:58 -04:00
|
|
|
|
2021-04-12 10:13:29 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
bo = gbm_bo_create (gbm_device, cursor_width, cursor_height,
|
2015-03-10 23:16:58 -04:00
|
|
|
gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
2015-07-17 11:16:39 -04:00
|
|
|
if (!bo)
|
|
|
|
{
|
2020-10-02 11:47:22 -04:00
|
|
|
meta_warning ("Failed to allocate HW cursor buffer");
|
2015-07-17 11:16:39 -04:00
|
|
|
return;
|
|
|
|
}
|
2015-03-10 23:16:58 -04:00
|
|
|
|
|
|
|
memset (buf, 0, sizeof(buf));
|
|
|
|
for (i = 0; i < height; i++)
|
|
|
|
memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
|
2015-07-17 11:16:39 -04:00
|
|
|
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;
|
|
|
|
}
|
2015-03-10 23:16:58 -04:00
|
|
|
|
2021-04-12 10:13:29 -04:00
|
|
|
buffer_gbm = meta_drm_buffer_gbm_new_take (device_file, bo, FALSE, &error);
|
2020-09-21 13:32:46 -04:00
|
|
|
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));
|
2015-03-10 23:16:58 -04:00
|
|
|
}
|
|
|
|
else
|
2015-07-17 11:16:39 -04:00
|
|
|
{
|
2020-10-02 11:47:22 -04:00
|
|
|
meta_warning ("HW cursor for format %d not supported", gbm_format);
|
2015-07-17 11:16:39 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-02 10:56:53 -04:00
|
|
|
static gboolean
|
|
|
|
is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite,
|
|
|
|
MetaGpuKms *gpu_kms)
|
2015-07-17 11:16:39 -04:00
|
|
|
{
|
2017-07-24 22:31:25 -04:00
|
|
|
MetaCursorNativePrivate *cursor_priv;
|
|
|
|
MetaCursorNativeGpuState *cursor_gpu_state;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
cursor_priv = get_cursor_priv (cursor_sprite);
|
2015-07-17 11:16:39 -04:00
|
|
|
if (!cursor_priv)
|
2018-05-02 10:56:53 -04:00
|
|
|
return FALSE;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);
|
|
|
|
if (!cursor_gpu_state)
|
2018-05-02 10:56:53 -04:00
|
|
|
return FALSE;
|
2017-07-24 22:31:25 -04:00
|
|
|
|
2020-09-21 13:32:46 -04:00
|
|
|
switch (cursor_gpu_state->pending_buffer_state)
|
2018-05-02 10:56:53 -04:00
|
|
|
{
|
2020-09-21 13:32:46 -04:00
|
|
|
case META_CURSOR_BUFFER_STATE_SET:
|
|
|
|
case META_CURSOR_BUFFER_STATE_NONE:
|
2018-05-02 10:56:53 -04:00
|
|
|
return TRUE;
|
2020-09-21 13:32:46 -04:00
|
|
|
case META_CURSOR_BUFFER_STATE_INVALIDATED:
|
2018-05-02 10:56:53 -04:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert_not_reached ();
|
2019-01-24 18:47:44 -05:00
|
|
|
return FALSE;
|
2015-03-10 23:16:58 -04:00
|
|
|
}
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-10 23:16:58 -04:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
static void
|
2018-05-02 06:27:02 -04:00
|
|
|
realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer,
|
|
|
|
MetaGpuKms *gpu_kms,
|
2018-05-02 14:32:43 -04:00
|
|
|
MetaCursorSpriteWayland *sprite_wayland)
|
2015-03-10 23:16:58 -04:00
|
|
|
{
|
|
|
|
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
2021-04-12 10:13:29 -04:00
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (native);
|
2018-05-02 06:27:02 -04:00
|
|
|
MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_wayland);
|
2017-07-24 22:31:25 -04:00
|
|
|
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
2015-03-10 23:16:58 -04:00
|
|
|
uint64_t cursor_width, cursor_height;
|
2015-07-17 11:16:39 -04:00
|
|
|
CoglTexture *texture;
|
2015-03-10 23:16:58 -04:00
|
|
|
uint width, height;
|
2018-05-02 14:32:43 -04:00
|
|
|
MetaWaylandBuffer *buffer;
|
|
|
|
struct wl_resource *buffer_resource;
|
|
|
|
struct wl_shm_buffer *shm_buffer;
|
2015-03-10 23:16:58 -04:00
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
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)
|
2016-09-27 01:39:45 -04:00
|
|
|
return;
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) &&
|
|
|
|
is_cursor_scale_and_transform_valid (renderer, cursor_sprite))
|
2018-05-02 10:56:53 -04:00
|
|
|
return;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2018-05-02 14:32:43 -04:00
|
|
|
buffer = meta_cursor_sprite_wayland_get_buffer (sprite_wayland);
|
|
|
|
if (!buffer)
|
|
|
|
return;
|
|
|
|
|
|
|
|
buffer_resource = meta_wayland_buffer_get_resource (buffer);
|
|
|
|
if (!buffer_resource)
|
|
|
|
return;
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
ensure_cursor_priv (cursor_sprite);
|
|
|
|
|
2018-05-02 14:32:43 -04:00
|
|
|
shm_buffer = wl_shm_buffer_get (buffer_resource);
|
2015-03-10 23:16:58 -04:00
|
|
|
if (shm_buffer)
|
|
|
|
{
|
|
|
|
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
|
|
|
uint8_t *buffer_data;
|
2019-05-13 04:21:40 -04:00
|
|
|
float relative_scale;
|
|
|
|
MetaMonitorTransform relative_transform;
|
|
|
|
uint32_t gbm_format;
|
2015-03-10 23:16:58 -04:00
|
|
|
|
2020-03-14 10:52:38 -04:00
|
|
|
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);
|
|
|
|
|
2015-03-10 23:16:58 -04:00
|
|
|
wl_shm_buffer_begin_access (shm_buffer);
|
2019-05-13 04:21:40 -04:00
|
|
|
buffer_data = wl_shm_buffer_get_data (shm_buffer);
|
|
|
|
|
|
|
|
width = wl_shm_buffer_get_width (shm_buffer);
|
2020-02-28 16:21:13 -05:00
|
|
|
height = wl_shm_buffer_get_height (shm_buffer);
|
2015-03-10 23:16:58 -04:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
load_scaled_and_transformed_cursor_sprite (native,
|
|
|
|
gpu_kms,
|
|
|
|
cursor_sprite,
|
|
|
|
relative_scale,
|
|
|
|
relative_transform,
|
|
|
|
buffer_data,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
rowstride,
|
|
|
|
gbm_format);
|
2015-03-10 23:16:58 -04:00
|
|
|
|
|
|
|
wl_shm_buffer_end_access (shm_buffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-04-12 10:13:29 -04:00
|
|
|
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;
|
2017-07-24 22:31:25 -04:00
|
|
|
struct gbm_device *gbm_device;
|
2015-03-10 23:16:58 -04:00
|
|
|
struct gbm_bo *bo;
|
2020-09-21 13:32:46 -04:00
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
MetaDrmBufferGbm *buffer_gbm;
|
2015-03-10 23:16:58 -04:00
|
|
|
|
2021-04-12 10:13:29 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-03-10 23:16:58 -04:00
|
|
|
/* 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. */
|
2017-07-24 22:31:25 -04:00
|
|
|
cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width;
|
|
|
|
cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height;
|
2015-03-10 23:16:58 -04:00
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
|
|
|
|
width = cogl_texture_get_width (texture);
|
|
|
|
height = cogl_texture_get_height (texture);
|
|
|
|
|
2015-03-10 23:16:58 -04:00
|
|
|
if (width != cursor_width || height != cursor_height)
|
|
|
|
{
|
2020-10-02 11:47:22 -04:00
|
|
|
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors");
|
2015-03-10 23:16:58 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-07-24 22:31:25 -04:00
|
|
|
gbm_device = meta_gbm_device_from_gpu (gpu_kms);
|
|
|
|
bo = gbm_bo_import (gbm_device,
|
2015-03-10 23:16:58 -04:00
|
|
|
GBM_BO_IMPORT_WL_BUFFER,
|
|
|
|
buffer,
|
|
|
|
GBM_BO_USE_CURSOR);
|
|
|
|
if (!bo)
|
|
|
|
{
|
2020-10-02 11:47:22 -04:00
|
|
|
meta_warning ("Importing HW cursor from wl_buffer failed");
|
2015-03-10 23:16:58 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
unset_can_preprocess (cursor_sprite);
|
|
|
|
|
2021-04-12 10:13:29 -04:00
|
|
|
buffer_gbm = meta_drm_buffer_gbm_new_take (device_file, bo, FALSE, &error);
|
2020-09-21 13:32:46 -04:00
|
|
|
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));
|
2015-03-10 23:16:58 -04:00
|
|
|
}
|
|
|
|
}
|
2017-07-24 22:31:25 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static void
|
2018-05-02 06:23:49 -04:00
|
|
|
realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer,
|
|
|
|
MetaGpuKms *gpu_kms,
|
2018-05-02 14:32:43 -04:00
|
|
|
MetaCursorSpriteXcursor *sprite_xcursor)
|
2017-07-24 22:31:25 -04:00
|
|
|
{
|
|
|
|
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
|
|
|
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
2018-04-30 06:55:08 -04:00
|
|
|
MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor);
|
2018-05-02 14:32:43 -04:00
|
|
|
XcursorImage *xc_image;
|
2019-05-13 04:21:40 -04:00
|
|
|
float relative_scale;
|
|
|
|
MetaMonitorTransform relative_transform;
|
|
|
|
|
|
|
|
ensure_cursor_priv (cursor_sprite);
|
2017-07-24 22:31:25 -04:00
|
|
|
|
|
|
|
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)
|
2016-09-27 01:39:45 -04:00
|
|
|
return;
|
2015-03-10 23:16:58 -04:00
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) &&
|
|
|
|
is_cursor_scale_and_transform_valid (renderer, cursor_sprite))
|
2018-05-02 10:56:53 -04:00
|
|
|
return;
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2020-03-14 10:52:38 -04:00
|
|
|
if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer,
|
|
|
|
cursor_sprite,
|
|
|
|
&relative_scale))
|
|
|
|
{
|
|
|
|
unset_can_preprocess (cursor_sprite);
|
|
|
|
return;
|
|
|
|
}
|
2019-05-13 04:21:40 -04:00
|
|
|
|
2020-03-14 10:52:38 -04:00
|
|
|
if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer,
|
|
|
|
cursor_sprite,
|
|
|
|
&relative_transform))
|
|
|
|
{
|
|
|
|
unset_can_preprocess (cursor_sprite);
|
|
|
|
return;
|
|
|
|
}
|
2019-05-13 04:21:40 -04:00
|
|
|
|
|
|
|
set_can_preprocess (cursor_sprite,
|
|
|
|
relative_scale,
|
|
|
|
relative_transform);
|
|
|
|
|
2020-03-14 10:52:38 -04:00
|
|
|
xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor);
|
|
|
|
|
2019-05-13 04:21:40 -04:00
|
|
|
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);
|
2017-07-24 22:31:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-05-02 14:32:43 -04:00
|
|
|
realize_cursor_sprite_for_gpu (MetaCursorRenderer *renderer,
|
|
|
|
MetaGpuKms *gpu_kms,
|
|
|
|
MetaCursorSprite *cursor_sprite)
|
2017-07-24 22:31:25 -04:00
|
|
|
{
|
2018-05-02 08:34:02 -04:00
|
|
|
if (META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite))
|
|
|
|
{
|
|
|
|
MetaCursorSpriteXcursor *sprite_xcursor =
|
|
|
|
META_CURSOR_SPRITE_XCURSOR (cursor_sprite);
|
|
|
|
|
2018-05-02 14:32:43 -04:00
|
|
|
realize_cursor_sprite_from_xcursor_for_gpu (renderer,
|
|
|
|
gpu_kms,
|
|
|
|
sprite_xcursor);
|
2018-05-02 08:34:02 -04:00
|
|
|
}
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
else if (META_IS_CURSOR_SPRITE_WAYLAND (cursor_sprite))
|
|
|
|
{
|
|
|
|
MetaCursorSpriteWayland *sprite_wayland =
|
|
|
|
META_CURSOR_SPRITE_WAYLAND (cursor_sprite);
|
|
|
|
|
2018-05-02 14:32:43 -04:00
|
|
|
realize_cursor_sprite_from_wl_buffer_for_gpu (renderer,
|
|
|
|
gpu_kms,
|
|
|
|
sprite_wayland);
|
2018-05-02 08:34:02 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-05-02 14:32:43 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-22 15:15:11 -04:00
|
|
|
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;
|
2015-03-10 23:16:58 -04:00
|
|
|
|
|
|
|
quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native");
|
2017-07-24 22:31:25 -04:00
|
|
|
quark_cursor_renderer_native_gpu_data =
|
|
|
|
g_quark_from_static_string ("-meta-cursor-renderer-native-gpu-data");
|
2014-04-22 15:15:11 -04:00
|
|
|
}
|
|
|
|
|
2015-07-17 11:16:39 -04:00
|
|
|
static void
|
|
|
|
force_update_hw_cursor (MetaCursorRendererNative *native)
|
|
|
|
{
|
|
|
|
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
|
2017-01-10 03:01:46 -05:00
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (native);
|
2020-10-09 19:02:28 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2015-07-17 11:16:39 -04:00
|
|
|
|
2018-05-09 12:50:37 -04:00
|
|
|
meta_cursor_renderer_force_update (renderer);
|
2015-07-17 11:16:39 -04:00
|
|
|
}
|
|
|
|
|
2014-04-22 15:15:11 -04:00
|
|
|
static void
|
|
|
|
on_monitors_changed (MetaMonitorManager *monitors,
|
|
|
|
MetaCursorRendererNative *native)
|
|
|
|
{
|
2015-07-17 11:16:39 -04:00
|
|
|
force_update_hw_cursor (native);
|
2014-04-22 15:15:11 -04:00
|
|
|
}
|
|
|
|
|
2020-02-24 08:13:42 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-02-24 08:36:24 -05:00
|
|
|
static void
|
|
|
|
on_gpu_added_for_cursor (MetaBackend *backend,
|
|
|
|
MetaGpuKms *gpu_kms)
|
|
|
|
{
|
|
|
|
init_hw_cursor_support_for_gpu (gpu_kms);
|
|
|
|
}
|
|
|
|
|
2014-04-22 15:15:11 -04:00
|
|
|
static void
|
2017-07-10 06:19:32 -04:00
|
|
|
init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native)
|
2014-04-22 15:15:11 -04:00
|
|
|
{
|
2017-07-07 04:12:07 -04:00
|
|
|
MetaCursorRendererNativePrivate *priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
|
2017-07-10 06:19:32 -04:00
|
|
|
GList *gpus;
|
2017-07-24 22:31:25 -04:00
|
|
|
GList *l;
|
2014-04-22 15:15:11 -04:00
|
|
|
|
2019-01-11 09:35:42 -05:00
|
|
|
gpus = meta_backend_get_gpus (priv->backend);
|
2017-07-24 22:31:25 -04:00
|
|
|
for (l = gpus; l; l = l->next)
|
|
|
|
{
|
|
|
|
MetaGpuKms *gpu_kms = l->data;
|
2019-11-09 05:47:34 -05:00
|
|
|
|
2020-02-24 08:13:42 -05:00
|
|
|
init_hw_cursor_support_for_gpu (gpu_kms);
|
2017-07-07 04:12:07 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaCursorRendererNative *
|
2020-07-13 07:32:48 -04:00
|
|
|
meta_cursor_renderer_native_new (MetaBackend *backend,
|
|
|
|
ClutterInputDevice *device)
|
2017-07-07 04:12:07 -04:00
|
|
|
{
|
|
|
|
MetaMonitorManager *monitor_manager =
|
|
|
|
meta_backend_get_monitor_manager (backend);
|
|
|
|
MetaCursorRendererNative *cursor_renderer_native;
|
|
|
|
MetaCursorRendererNativePrivate *priv;
|
|
|
|
|
2020-05-27 03:29:04 -04:00
|
|
|
cursor_renderer_native = g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE,
|
|
|
|
"backend", backend,
|
2020-07-13 07:32:48 -04:00
|
|
|
"device", device,
|
2020-05-27 03:29:04 -04:00
|
|
|
NULL);
|
2017-07-07 04:12:07 -04:00
|
|
|
priv =
|
|
|
|
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
|
|
|
|
|
2017-10-12 20:14:40 -04:00
|
|
|
g_signal_connect_object (monitor_manager, "monitors-changed-internal",
|
2017-07-07 04:12:07 -04:00
|
|
|
G_CALLBACK (on_monitors_changed),
|
|
|
|
cursor_renderer_native, 0);
|
2020-02-24 08:36:24 -05:00
|
|
|
g_signal_connect (backend, "gpu-added",
|
|
|
|
G_CALLBACK (on_gpu_added_for_cursor), NULL);
|
2017-07-07 04:12:07 -04:00
|
|
|
|
2019-01-11 09:35:42 -05:00
|
|
|
priv->backend = backend;
|
2017-07-07 04:12:07 -04:00
|
|
|
|
2017-07-10 06:19:32 -04:00
|
|
|
init_hw_cursor_support (cursor_renderer_native);
|
2017-07-07 04:12:07 -04:00
|
|
|
|
|
|
|
return cursor_renderer_native;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
|
|
|
|
{
|
2014-04-22 15:15:11 -04:00
|
|
|
}
|