cursor-renderer-native: Port to transactional KMS api

Turns the cursor setting and movement into cursor plane assignment
primitives. In the current simple implementation, this in turn
translates into legacy drmModeSetCursor() and drmModeMoveCursor() calls.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/930
This commit is contained in:
Jonas Ådahl 2019-11-09 00:19:51 +01:00
parent 7c3172a0af
commit ae00f5653e

View File

@ -37,6 +37,10 @@
#include "backends/meta-monitor.h" #include "backends/meta-monitor.h"
#include "backends/meta-monitor-manager-private.h" #include "backends/meta-monitor-manager-private.h"
#include "backends/meta-output.h" #include "backends/meta-output.h"
#include "backends/native/meta-crtc-kms.h"
#include "backends/native/meta-kms-device.h"
#include "backends/native/meta-kms-update.h"
#include "backends/native/meta-kms.h"
#include "backends/native/meta-renderer-native.h" #include "backends/native/meta-renderer-native.h"
#include "core/boxes-private.h" #include "core/boxes-private.h"
#include "meta/boxes.h" #include "meta/boxes.h"
@ -211,82 +215,109 @@ set_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite,
static void static void
set_crtc_cursor (MetaCursorRendererNative *native, set_crtc_cursor (MetaCursorRendererNative *native,
MetaKmsUpdate *kms_update,
MetaCrtc *crtc, MetaCrtc *crtc,
int x,
int y,
MetaCursorSprite *cursor_sprite) MetaCursorSprite *cursor_sprite)
{ {
MetaCursorRendererNativePrivate *priv = MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native); meta_cursor_renderer_native_get_instance_private (native);
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite);
MetaGpuKms *gpu_kms; MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
int kms_fd; MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data =
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
cursor_renderer_gpu_data =
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
kms_fd = meta_gpu_kms_get_fd (gpu_kms); MetaCursorNativeGpuState *cursor_gpu_state =
get_cursor_gpu_state (cursor_priv, gpu_kms);
MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
MetaKmsPlane *cursor_plane;
struct gbm_bo *bo;
union gbm_bo_handle handle;
int cursor_width, cursor_height;
MetaFixed16Rectangle src_rect;
MetaFixed16Rectangle dst_rect;
MetaKmsAssignPlaneFlag flags;
if (cursor_sprite) if (cursor_gpu_state->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
{ bo = get_pending_cursor_sprite_gbm_bo (cursor_gpu_state);
MetaCursorNativePrivate *cursor_priv;
MetaCursorNativeGpuState *cursor_gpu_state;
struct gbm_bo *bo;
union gbm_bo_handle handle;
int hot_x, hot_y;
cursor_priv = get_cursor_priv (cursor_sprite);
cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);
if (cursor_gpu_state->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
bo = get_pending_cursor_sprite_gbm_bo (cursor_gpu_state);
else
bo = get_active_cursor_sprite_gbm_bo (cursor_gpu_state);
if (!priv->hw_state_invalidated && bo == crtc->cursor_renderer_private)
return;
crtc->cursor_renderer_private = bo;
handle = gbm_bo_get_handle (bo);
meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y);
if (drmModeSetCursor2 (kms_fd, crtc->crtc_id, handle.u32,
cursor_renderer_gpu_data->cursor_width,
cursor_renderer_gpu_data->cursor_height,
hot_x, hot_y) < 0)
{
if (errno != EACCES)
{
g_warning ("drmModeSetCursor2 failed with (%s), "
"drawing cursor with OpenGL from now on",
strerror (errno));
priv->has_hw_cursor = FALSE;
cursor_renderer_gpu_data->hw_cursor_broken = TRUE;
}
}
if (cursor_gpu_state->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
{
cursor_gpu_state->active_bo =
(cursor_gpu_state->active_bo + 1) % HW_CURSOR_BUFFER_COUNT;
cursor_gpu_state->pending_bo_state = META_CURSOR_GBM_BO_STATE_NONE;
}
}
else else
bo = get_active_cursor_sprite_gbm_bo (cursor_gpu_state);
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
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);
handle = gbm_bo_get_handle (bo);
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 = (MetaFixed16Rectangle) {
.x = meta_fixed_16_from_int (x),
.y = meta_fixed_16_from_int (y),
.width = meta_fixed_16_from_int (cursor_width),
.height = meta_fixed_16_from_int (cursor_height),
};
flags = META_KMS_ASSIGN_PLANE_FLAG_NONE;
if (!priv->hw_state_invalidated && bo == crtc->cursor_renderer_private)
flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED;
meta_kms_update_assign_plane (kms_update,
kms_crtc,
cursor_plane,
handle.u32,
src_rect,
dst_rect,
flags);
crtc->cursor_renderer_private = bo;
if (cursor_gpu_state->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET)
{ {
if (priv->hw_state_invalidated || crtc->cursor_renderer_private != NULL) cursor_gpu_state->active_bo =
{ (cursor_gpu_state->active_bo + 1) % HW_CURSOR_BUFFER_COUNT;
drmModeSetCursor2 (kms_fd, crtc->crtc_id, 0, 0, 0, 0, 0); cursor_gpu_state->pending_bo_state = META_CURSOR_GBM_BO_STATE_NONE;
crtc->cursor_renderer_private = NULL;
}
} }
} }
static void
unset_crtc_cursor (MetaCursorRendererNative *native,
MetaKmsUpdate *kms_update,
MetaCrtc *crtc)
{
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
MetaKmsPlane *cursor_plane;
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
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);
if (!priv->hw_state_invalidated && !crtc->cursor_renderer_private)
return;
meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane);
crtc->cursor_renderer_private = NULL;
}
typedef struct typedef struct
{ {
MetaCursorRendererNative *in_cursor_renderer_native; MetaCursorRendererNative *in_cursor_renderer_native;
MetaLogicalMonitor *in_logical_monitor; MetaLogicalMonitor *in_logical_monitor;
graphene_rect_t in_local_cursor_rect; graphene_rect_t in_local_cursor_rect;
MetaCursorSprite *in_cursor_sprite; MetaCursorSprite *in_cursor_sprite;
MetaKmsUpdate *in_kms_update;
gboolean out_painted; gboolean out_painted;
} UpdateCrtcCursorData; } UpdateCrtcCursorData;
@ -351,35 +382,47 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
&data->in_local_cursor_rect, &data->in_local_cursor_rect,
NULL)) NULL))
{ {
MetaGpuKms *gpu_kms;
int kms_fd;
float crtc_cursor_x, crtc_cursor_y; float crtc_cursor_x, crtc_cursor_y;
set_crtc_cursor (data->in_cursor_renderer_native,
crtc,
data->in_cursor_sprite);
gpu_kms = META_GPU_KMS (meta_monitor_get_gpu (monitor));
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
crtc_cursor_x = (data->in_local_cursor_rect.origin.x - crtc_cursor_x = (data->in_local_cursor_rect.origin.x -
scaled_crtc_rect.origin.x) * scale; scaled_crtc_rect.origin.x) * scale;
crtc_cursor_y = (data->in_local_cursor_rect.origin.y - crtc_cursor_y = (data->in_local_cursor_rect.origin.y -
scaled_crtc_rect.origin.y) * scale; scaled_crtc_rect.origin.y) * scale;
drmModeMoveCursor (kms_fd,
crtc->crtc_id, set_crtc_cursor (data->in_cursor_renderer_native,
floorf (crtc_cursor_x), data->in_kms_update,
floorf (crtc_cursor_y)); crtc,
(int) floorf (crtc_cursor_x),
(int) floorf (crtc_cursor_y),
data->in_cursor_sprite);
data->out_painted = data->out_painted || TRUE; data->out_painted = data->out_painted || TRUE;
} }
else else
{ {
set_crtc_cursor (data->in_cursor_renderer_native, crtc, NULL); unset_crtc_cursor (data->in_cursor_renderer_native,
data->in_kms_update,
crtc);
} }
return TRUE; return TRUE;
} }
static void
disable_hw_cursor_for_crtc (MetaKmsCrtc *kms_crtc,
const GError *error)
{
MetaCrtc *crtc = meta_crtc_kms_from_kms_crtc (kms_crtc);
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;
}
static void static void
update_hw_cursor (MetaCursorRendererNative *native, update_hw_cursor (MetaCursorRendererNative *native,
MetaCursorSprite *cursor_sprite) MetaCursorSprite *cursor_sprite)
@ -388,12 +431,18 @@ update_hw_cursor (MetaCursorRendererNative *native,
meta_cursor_renderer_native_get_instance_private (native); meta_cursor_renderer_native_get_instance_private (native);
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
MetaBackend *backend = priv->backend; MetaBackend *backend = priv->backend;
MetaBackendNative *backend_native = META_BACKEND_NATIVE (priv->backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
MetaMonitorManager *monitor_manager = MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend); meta_backend_get_monitor_manager (backend);
MetaKmsUpdate *kms_update;
GList *logical_monitors; GList *logical_monitors;
GList *l; GList *l;
graphene_rect_t rect; graphene_rect_t rect;
gboolean painted = FALSE; gboolean painted = FALSE;
g_autoptr (MetaKmsFeedback) feedback = NULL;
kms_update = meta_kms_ensure_pending_update (kms);
if (cursor_sprite) if (cursor_sprite)
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
@ -419,7 +468,8 @@ update_hw_cursor (MetaCursorRendererNative *native,
}, },
.size = rect.size .size = rect.size
}, },
.in_cursor_sprite = cursor_sprite .in_cursor_sprite = cursor_sprite,
.in_kms_update = kms_update,
}; };
monitors = meta_logical_monitor_get_monitors (logical_monitor); monitors = meta_logical_monitor_get_monitors (logical_monitor);
@ -438,6 +488,25 @@ update_hw_cursor (MetaCursorRendererNative *native,
painted = painted || data.out_painted; painted = painted || data.out_painted;
} }
feedback = meta_kms_post_pending_update_sync (kms);
if (meta_kms_feedback_get_result (feedback) != META_KMS_FEEDBACK_PASSED)
{
for (l = meta_kms_feedback_get_failed_planes (feedback); l; l = l->next)
{
MetaKmsPlaneFeedback *plane_feedback = l->data;
if (!g_error_matches (plane_feedback->error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
{
disable_hw_cursor_for_crtc (plane_feedback->crtc,
plane_feedback->error);
}
}
priv->has_hw_cursor = FALSE;
}
priv->hw_state_invalidated = FALSE; priv->hw_state_invalidated = FALSE;
if (painted) if (painted)