cursor-renderer/native: Update HW state during frames

Before each frame is maybe redrawn, push any new cursor KMS state to the
pending update. It'll then either be posted during the next page flip,
or when the same frame finishes, in case nothing was redrawn.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>
This commit is contained in:
Jonas Ådahl 2020-10-10 01:02:28 +02:00 committed by Marge Bot
parent 487ea0dd95
commit c985753442
12 changed files with 359 additions and 257 deletions

View File

@ -1099,6 +1099,8 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock,
frame = CLUTTER_FRAME_INIT; frame = CLUTTER_FRAME_INIT;
_clutter_stage_window_prepare_frame (stage_window, view, &frame);
if (clutter_stage_view_has_redraw_clip (view)) if (clutter_stage_view_has_redraw_clip (view))
{ {
clutter_stage_emit_before_paint (stage, view); clutter_stage_emit_before_paint (stage, view);

View File

@ -135,6 +135,17 @@ _clutter_stage_window_get_views (ClutterStageWindow *window)
return iface->get_views (window); return iface->get_views (window);
} }
void
_clutter_stage_window_prepare_frame (ClutterStageWindow *window,
ClutterStageView *view,
ClutterFrame *frame)
{
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->prepare_frame)
iface->prepare_frame (window, view, frame);
}
void void
_clutter_stage_window_finish_frame (ClutterStageWindow *window, _clutter_stage_window_finish_frame (ClutterStageWindow *window,
ClutterStageView *view, ClutterStageView *view,

View File

@ -52,6 +52,9 @@ struct _ClutterStageWindowInterface
GList *(* get_views) (ClutterStageWindow *stage_window); GList *(* get_views) (ClutterStageWindow *stage_window);
int64_t (* get_frame_counter) (ClutterStageWindow *stage_window); int64_t (* get_frame_counter) (ClutterStageWindow *stage_window);
void (* prepare_frame) (ClutterStageWindow *stage_window,
ClutterStageView *view,
ClutterFrame *frame);
void (* finish_frame) (ClutterStageWindow *stage_window, void (* finish_frame) (ClutterStageWindow *stage_window,
ClutterStageView *view, ClutterStageView *view,
ClutterFrame *frame); ClutterFrame *frame);
@ -89,6 +92,10 @@ gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWin
GList * _clutter_stage_window_get_views (ClutterStageWindow *window); GList * _clutter_stage_window_get_views (ClutterStageWindow *window);
void _clutter_stage_window_prepare_frame (ClutterStageWindow *window,
ClutterStageView *view,
ClutterFrame *frame);
void _clutter_stage_window_finish_frame (ClutterStageWindow *window, void _clutter_stage_window_finish_frame (ClutterStageWindow *window,
ClutterStageView *view, ClutterStageView *view,
ClutterFrame *frame); ClutterFrame *frame);

View File

@ -731,6 +731,21 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
clutter_stage_cogl_redraw_view_primary (stage_cogl, view, frame); clutter_stage_cogl_redraw_view_primary (stage_cogl, view, frame);
} }
void
clutter_stage_cogl_add_onscreen_frame_info (ClutterStageCogl *stage_cogl,
ClutterStageView *view)
{
ClutterStageCoglPrivate *priv =
_clutter_stage_cogl_get_instance_private (stage_cogl);
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
CoglFrameInfo *frame_info;
frame_info = cogl_frame_info_new (priv->global_frame_counter);
priv->global_frame_counter++;
cogl_onscreen_add_frame_info (COGL_ONSCREEN (framebuffer), frame_info);
}
static void static void
clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
{ {

View File

@ -56,6 +56,10 @@ void _clutter_stage_cogl_presented (ClutterStageCogl *stage_cogl,
CoglFrameEvent frame_event, CoglFrameEvent frame_event,
ClutterFrameInfo *frame_info); ClutterFrameInfo *frame_info);
CLUTTER_EXPORT
void clutter_stage_cogl_add_onscreen_frame_info (ClutterStageCogl *stage_cogl,
ClutterStageView *view);
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_STAGE_COGL_H__ */ #endif /* __CLUTTER_STAGE_COGL_H__ */

View File

@ -1948,6 +1948,28 @@ meta_monitor_mode_foreach_output (MetaMonitor *monitor,
return TRUE; return TRUE;
} }
MetaMonitorCrtcMode *
meta_monitor_get_crtc_mode_for_output (MetaMonitor *monitor,
MetaMonitorMode *mode,
MetaOutput *output)
{
MetaMonitorPrivate *monitor_priv =
meta_monitor_get_instance_private (monitor);
GList *l;
int i;
for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
{
MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i];
if (monitor_crtc_mode->output == output)
return monitor_crtc_mode;
}
g_warn_if_reached ();
return NULL;
}
const char * const char *
meta_monitor_get_display_name (MetaMonitor *monitor) meta_monitor_get_display_name (MetaMonitor *monitor)
{ {

View File

@ -264,6 +264,10 @@ gboolean meta_monitor_mode_foreach_output (MetaMonitor *monitor,
gpointer user_data, gpointer user_data,
GError **error); GError **error);
MetaMonitorCrtcMode * meta_monitor_get_crtc_mode_for_output (MetaMonitor *monitor,
MetaMonitorMode *mode,
MetaOutput *output);
META_EXPORT_TEST META_EXPORT_TEST
gboolean meta_monitor_mode_should_be_advertised (MetaMonitorMode *monitor_mode); gboolean meta_monitor_mode_should_be_advertised (MetaMonitorMode *monitor_mode);

View File

@ -80,6 +80,8 @@ static GQuark quark_cursor_sprite = 0;
typedef struct _CrtcCursorData typedef struct _CrtcCursorData
{ {
MetaDrmBuffer *buffer; MetaDrmBuffer *buffer;
gboolean needs_sync_position;
gboolean hw_state_invalidated;
} CrtcCursorData; } CrtcCursorData;
struct _MetaCursorRendererNative struct _MetaCursorRendererNative
@ -91,7 +93,6 @@ struct _MetaCursorRendererNativePrivate
{ {
MetaBackend *backend; MetaBackend *backend;
gboolean hw_state_invalidated;
gboolean has_hw_cursor; gboolean has_hw_cursor;
MetaCursorSprite *last_cursor; MetaCursorSprite *last_cursor;
@ -137,6 +138,10 @@ static GQuark quark_cursor_renderer_native_gpu_data = 0;
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER); G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER);
static void
on_kms_update_result (const MetaKmsFeedback *kms_feedback,
gpointer user_data);
static void static void
realize_cursor_sprite (MetaCursorRenderer *renderer, realize_cursor_sprite (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite, MetaCursorSprite *cursor_sprite,
@ -266,6 +271,7 @@ ensure_crtc_cursor_data (MetaCrtcKms *crtc_kms)
if (!crtc_cursor_data) if (!crtc_cursor_data)
{ {
crtc_cursor_data = g_new0 (CrtcCursorData, 1); crtc_cursor_data = g_new0 (CrtcCursorData, 1);
crtc_cursor_data->hw_state_invalidated = TRUE;
meta_crtc_kms_set_cursor_renderer_private (crtc_kms, meta_crtc_kms_set_cursor_renderer_private (crtc_kms,
crtc_cursor_data, crtc_cursor_data,
g_free); g_free);
@ -275,15 +281,12 @@ ensure_crtc_cursor_data (MetaCrtcKms *crtc_kms)
} }
static void static void
set_crtc_cursor (MetaCursorRendererNative *native, assign_cursor_plane (MetaCursorRendererNative *native,
MetaKmsUpdate *kms_update,
MetaCrtcKms *crtc_kms, MetaCrtcKms *crtc_kms,
int x, int x,
int y, int y,
MetaCursorSprite *cursor_sprite) MetaCursorSprite *cursor_sprite)
{ {
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
MetaCrtc *crtc = META_CRTC (crtc_kms); MetaCrtc *crtc = META_CRTC (crtc_kms);
MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite);
MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
@ -303,6 +306,7 @@ set_crtc_cursor (MetaCursorRendererNative *native,
CrtcCursorData *crtc_cursor_data; CrtcCursorData *crtc_cursor_data;
int cursor_hotspot_x; int cursor_hotspot_x;
int cursor_hotspot_y; int cursor_hotspot_y;
MetaKmsUpdate *kms_update;
MetaKmsPlaneAssignment *plane_assignment; MetaKmsPlaneAssignment *plane_assignment;
if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET)
@ -333,9 +337,12 @@ set_crtc_cursor (MetaCursorRendererNative *native,
flags = META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL; flags = META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL;
crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms);
crtc_buffer = crtc_cursor_data->buffer; crtc_buffer = crtc_cursor_data->buffer;
if (!priv->hw_state_invalidated && buffer == crtc_buffer) if (!crtc_cursor_data->hw_state_invalidated && buffer == crtc_buffer)
flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED; flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED;
kms_update =
meta_kms_ensure_pending_update (meta_kms_device_get_kms (kms_device),
meta_kms_crtc_get_device (kms_crtc));
plane_assignment = meta_kms_update_assign_plane (kms_update, plane_assignment = meta_kms_update_assign_plane (kms_update,
kms_crtc, kms_crtc,
cursor_plane, cursor_plane,
@ -351,6 +358,10 @@ set_crtc_cursor (MetaCursorRendererNative *native,
cursor_hotspot_x, cursor_hotspot_x,
cursor_hotspot_y); cursor_hotspot_y);
meta_kms_update_add_result_listener (kms_update,
on_kms_update_result,
native);
crtc_cursor_data->buffer = buffer; crtc_cursor_data->buffer = buffer;
if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET)
@ -361,35 +372,6 @@ set_crtc_cursor (MetaCursorRendererNative *native,
} }
} }
static void
unset_crtc_cursor (MetaCursorRendererNative *native,
MetaKmsUpdate *kms_update,
MetaCrtcKms *crtc_kms)
{
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
MetaKmsPlane *cursor_plane;
MetaDrmBuffer *crtc_buffer;
CrtcCursorData *crtc_cursor_data;
crtc_buffer = meta_crtc_kms_get_cursor_renderer_private (crtc_kms);
if (!priv->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)
meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane);
crtc_cursor_data = meta_crtc_kms_get_cursor_renderer_private (crtc_kms);
if (crtc_cursor_data)
crtc_cursor_data->buffer = NULL;
}
static float static float
calculate_cursor_crtc_sprite_scale (MetaCursorSprite *cursor_sprite, calculate_cursor_crtc_sprite_scale (MetaCursorSprite *cursor_sprite,
MetaLogicalMonitor *logical_monitor) MetaLogicalMonitor *logical_monitor)
@ -405,107 +387,60 @@ calculate_cursor_crtc_sprite_scale (MetaCursorSprite *cursor_sprite,
} }
} }
typedef struct static void
set_crtc_cursor (MetaCursorRendererNative *cursor_renderer_native,
MetaRendererView *view,
MetaCrtc *crtc,
MetaCursorSprite *cursor_sprite)
{ {
MetaCursorRendererNative *in_cursor_renderer_native; MetaCursorRenderer *cursor_renderer =
MetaLogicalMonitor *in_logical_monitor; META_CURSOR_RENDERER (cursor_renderer_native);
graphene_rect_t in_local_cursor_rect; MetaOutput *output = meta_crtc_get_outputs (crtc)->data;
MetaCursorSprite *in_cursor_sprite; MetaMonitor *monitor = meta_output_get_monitor (output);
MetaLogicalMonitor *logical_monitor =
gboolean out_painted; meta_monitor_get_logical_monitor (monitor);
} UpdateCrtcCursorData; const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
graphene_rect_t rect;
static gboolean graphene_rect_t local_crtc_rect;
update_monitor_crtc_cursor (MetaMonitor *monitor, graphene_rect_t local_cursor_rect;
MetaMonitorMode *monitor_mode, float view_scale;
MetaMonitorCrtcMode *monitor_crtc_mode,
gpointer user_data,
GError **error)
{
UpdateCrtcCursorData *data = user_data;
MetaCursorRendererNative *cursor_renderer_native =
data->in_cursor_renderer_native;
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
MetaCrtc *crtc;
MetaGpuKms *gpu_kms;
MetaKmsDevice *kms_device;
MetaKms *kms;
MetaKmsUpdate *kms_update;
MetaMonitorTransform transform;
const MetaCrtcModeInfo *crtc_mode_info;
graphene_rect_t scaled_crtc_rect;
float scale;
int crtc_x, crtc_y;
int crtc_width, crtc_height;
if (meta_is_stage_views_scaled ())
scale = meta_logical_monitor_get_scale (data->in_logical_monitor);
else
scale = 1.0;
transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
meta_monitor_calculate_crtc_pos (monitor, monitor_mode,
monitor_crtc_mode->output,
transform,
&crtc_x, &crtc_y);
crtc_mode_info = meta_crtc_mode_get_info (monitor_crtc_mode->crtc_mode);
if (meta_monitor_transform_is_rotated (transform))
{
crtc_width = crtc_mode_info->height;
crtc_height = crtc_mode_info->width;
}
else
{
crtc_width = crtc_mode_info->width;
crtc_height = crtc_mode_info->height;
}
scaled_crtc_rect = (graphene_rect_t) {
.origin = {
.x = crtc_x / scale,
.y = crtc_y / scale
},
.size = {
.width = crtc_width / scale,
.height = crtc_height / scale
},
};
crtc = meta_output_get_assigned_crtc (monitor_crtc_mode->output);
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
kms = meta_kms_device_get_kms (kms_device);
kms_update = meta_kms_ensure_pending_update (kms, kms_device);
if (priv->has_hw_cursor &&
graphene_rect_intersection (&scaled_crtc_rect,
&data->in_local_cursor_rect,
NULL))
{
MetaMonitorTransform inverted_transform;
MetaRectangle cursor_rect;
CoglTexture *texture;
float crtc_cursor_x, crtc_cursor_y; float crtc_cursor_x, crtc_cursor_y;
float cursor_crtc_scale; CoglTexture *texture;
int tex_width, tex_height; int tex_width, tex_height;
float cursor_crtc_scale;
MetaRectangle cursor_rect;
MetaMonitorTransform transform;
MetaMonitorTransform inverted_transform;
MetaMonitorMode *monitor_mode;
MetaMonitorCrtcMode *monitor_crtc_mode;
const MetaCrtcModeInfo *crtc_mode_info;
crtc_cursor_x = (data->in_local_cursor_rect.origin.x - view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view));
scaled_crtc_rect.origin.x) * scale;
crtc_cursor_y = (data->in_local_cursor_rect.origin.y -
scaled_crtc_rect.origin.y) * scale;
texture = meta_cursor_sprite_get_cogl_texture (data->in_cursor_sprite); rect = meta_cursor_renderer_calculate_rect (cursor_renderer, cursor_sprite);
local_cursor_rect =
GRAPHENE_RECT_INIT (rect.origin.x - logical_monitor->rect.x,
rect.origin.y - logical_monitor->rect.y,
rect.size.width,
rect.size.height);
local_crtc_rect = crtc_config->layout;
graphene_rect_offset (&local_crtc_rect,
-logical_monitor->rect.x,
-logical_monitor->rect.y);
crtc_cursor_x = (local_cursor_rect.origin.x -
local_crtc_rect.origin.x) * view_scale;
crtc_cursor_y = (local_cursor_rect.origin.y -
local_crtc_rect.origin.y) * view_scale;
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
tex_width = cogl_texture_get_width (texture); tex_width = cogl_texture_get_width (texture);
tex_height = cogl_texture_get_height (texture); tex_height = cogl_texture_get_height (texture);
cursor_crtc_scale = cursor_crtc_scale =
calculate_cursor_crtc_sprite_scale (data->in_cursor_sprite, calculate_cursor_crtc_sprite_scale (cursor_sprite,
data->in_logical_monitor); logical_monitor);
cursor_rect = (MetaRectangle) { cursor_rect = (MetaRectangle) {
.x = floorf (crtc_cursor_x), .x = floorf (crtc_cursor_x),
@ -514,30 +449,59 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
.height = roundf (tex_height * cursor_crtc_scale) .height = roundf (tex_height * cursor_crtc_scale)
}; };
transform = meta_logical_monitor_get_transform (logical_monitor);
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
inverted_transform = meta_monitor_transform_invert (transform); 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, meta_rectangle_transform (&cursor_rect,
inverted_transform, inverted_transform,
crtc_mode_info->width, crtc_mode_info->width,
crtc_mode_info->height, crtc_mode_info->height,
&cursor_rect); &cursor_rect);
set_crtc_cursor (data->in_cursor_renderer_native, assign_cursor_plane (cursor_renderer_native,
kms_update,
META_CRTC_KMS (crtc), META_CRTC_KMS (crtc),
cursor_rect.x, cursor_rect.x,
cursor_rect.y, cursor_rect.y,
data->in_cursor_sprite); cursor_sprite);
data->out_painted = data->out_painted || TRUE;
} }
else
static void
unset_crtc_cursor (MetaCursorRendererNative *native,
MetaCrtc *crtc)
{ {
unset_crtc_cursor (data->in_cursor_renderer_native, MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc);
kms_update, CrtcCursorData *crtc_cursor_data;
META_CRTC_KMS (crtc)); MetaKmsCrtc *kms_crtc;
MetaKmsDevice *kms_device;
MetaKmsPlane *cursor_plane;
MetaDrmBuffer *crtc_buffer;
crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms);
crtc_buffer = crtc_cursor_data->buffer;
if (!crtc_cursor_data->hw_state_invalidated && !crtc_buffer)
return;
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
kms_device = meta_kms_crtc_get_device (kms_crtc);
cursor_plane = meta_kms_device_get_cursor_plane_for (kms_device, kms_crtc);
if (cursor_plane)
{
MetaKms *kms = meta_kms_device_get_kms (kms_device);
MetaKmsUpdate *kms_update;
kms_update = meta_kms_ensure_pending_update (kms, kms_device);
meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane);
} }
return TRUE; crtc_cursor_data->buffer = NULL;
} }
static void static void
@ -556,68 +520,61 @@ disable_hw_cursor_for_crtc (MetaKmsCrtc *kms_crtc,
cursor_renderer_gpu_data->hw_cursor_broken = TRUE; cursor_renderer_gpu_data->hw_cursor_broken = TRUE;
} }
static void void
update_hw_cursor (MetaCursorRendererNative *native, meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native,
MetaCursorSprite *cursor_sprite) MetaRendererView *view)
{ {
MetaCursorRenderer *cursor_renderer =
META_CURSOR_RENDERER (cursor_renderer_native);
MetaCursorRendererNativePrivate *priv = MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native); meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
MetaBackend *backend = priv->backend; MetaBackend *backend = priv->backend;
MetaMonitorManager *monitor_manager = MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend); meta_backend_get_monitor_manager (backend);
GList *logical_monitors; MetaCrtc *crtc = meta_renderer_view_get_crtc (view);
GList *l; MetaCursorSprite *cursor_sprite;
graphene_rect_t rect; graphene_rect_t cursor_rect;
gboolean painted = FALSE; cairo_rectangle_int_t view_layout;
graphene_rect_t view_rect;
CrtcCursorData *crtc_cursor_data;
if (cursor_sprite) if (meta_monitor_manager_get_power_save_mode (monitor_manager) !=
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); META_POWER_SAVE_ON)
else return;
rect = GRAPHENE_RECT_INIT_ZERO;
logical_monitors = crtc_cursor_data = ensure_crtc_cursor_data (META_CRTC_KMS (crtc));
meta_monitor_manager_get_logical_monitors (monitor_manager); if (!crtc_cursor_data->hw_state_invalidated &&
for (l = logical_monitors; l; l = l->next) !crtc_cursor_data->needs_sync_position)
{ return;
MetaLogicalMonitor *logical_monitor = l->data;
UpdateCrtcCursorData data;
GList *monitors;
GList *k;
data = (UpdateCrtcCursorData) { cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
.in_cursor_renderer_native = native, if (!cursor_sprite)
.in_logical_monitor = logical_monitor, goto unset_cursor;
.in_local_cursor_rect = (graphene_rect_t) {
.origin = {
.x = rect.origin.x - logical_monitor->rect.x,
.y = rect.origin.y - logical_monitor->rect.y
},
.size = rect.size
},
.in_cursor_sprite = cursor_sprite,
};
monitors = meta_logical_monitor_get_monitors (logical_monitor); if (!priv->has_hw_cursor)
for (k = monitors; k; k = k->next) goto unset_cursor;
{
MetaMonitor *monitor = k->data;
MetaMonitorMode *monitor_mode;
monitor_mode = meta_monitor_get_current_mode (monitor); cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer,
meta_monitor_mode_foreach_crtc (monitor, monitor_mode, cursor_sprite);
update_monitor_crtc_cursor, clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
&data, view_rect = GRAPHENE_RECT_INIT (view_layout.x, view_layout.y,
NULL); view_layout.width, view_layout.height);
} if (!graphene_rect_intersection (&cursor_rect, &view_rect, NULL))
goto unset_cursor;
painted = painted || data.out_painted; set_crtc_cursor (cursor_renderer_native, view, crtc, cursor_sprite);
}
priv->hw_state_invalidated = FALSE; meta_cursor_renderer_emit_painted (cursor_renderer, cursor_sprite);
if (painted) crtc_cursor_data->needs_sync_position = FALSE;
meta_cursor_renderer_emit_painted (renderer, cursor_sprite); crtc_cursor_data->hw_state_invalidated = FALSE;
return;
unset_cursor:
unset_crtc_cursor (cursor_renderer_native, crtc);
crtc_cursor_data = ensure_crtc_cursor_data (META_CRTC_KMS (crtc));
crtc_cursor_data->hw_state_invalidated = FALSE;
} }
static gboolean static gboolean
@ -1074,6 +1031,29 @@ on_kms_update_result (const MetaKmsFeedback *kms_feedback,
} }
} }
static void
schedule_sync_position (MetaCursorRendererNative *cursor_renderer_native)
{
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
GList *l;
for (l = meta_backend_get_gpus (priv->backend); l; l = l->next)
{
MetaGpu *gpu = l->data;
GList *l_crtc;
for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next)
{
MetaCrtcKms *crtc_kms = META_CRTC_KMS (l_crtc->data);
CrtcCursorData *crtc_cursor_data;
crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms);
crtc_cursor_data->needs_sync_position = TRUE;
}
}
}
static gboolean static gboolean
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer, meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite) MetaCursorSprite *cursor_sprite)
@ -1081,10 +1061,7 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
MetaCursorRendererNativePrivate *priv = MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native); meta_cursor_renderer_native_get_instance_private (native);
MetaRendererNative *renderer_native = ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (priv->backend));
META_RENDERER_NATIVE (meta_backend_get_renderer (priv->backend));
MetaBackendNative *backend_native = META_BACKEND_NATIVE (priv->backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
g_autoptr (GList) gpus = NULL; g_autoptr (GList) gpus = NULL;
if (cursor_sprite) if (cursor_sprite)
@ -1097,43 +1074,9 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite); maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite);
priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite, gpus); priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite, gpus);
update_hw_cursor (native, cursor_sprite);
if (!meta_renderer_native_is_mode_set_pending (renderer_native)) schedule_sync_position (native);
{ clutter_stage_schedule_update (stage);
GList *l;
for (l = meta_kms_get_devices (kms); l; l = l->next)
{
MetaKmsDevice *kms_device = l->data;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms,
kms_device,
flags);
on_kms_update_result (kms_feedback, renderer);
}
}
else
{
GList *l;
for (l = meta_kms_get_devices (kms); l; l = l->next)
{
MetaKmsDevice *kms_device = l->data;
MetaKmsUpdate *kms_update;
kms_update = meta_kms_get_pending_update (kms, kms_device);
if (!kms_update)
continue;
meta_kms_update_add_result_listener (kms_update,
on_kms_update_result,
renderer);
}
}
return (priv->has_hw_cursor || return (priv->has_hw_cursor ||
!cursor_sprite || !cursor_sprite ||
@ -1779,8 +1722,23 @@ force_update_hw_cursor (MetaCursorRendererNative *native)
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
MetaCursorRendererNativePrivate *priv = MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native); meta_cursor_renderer_native_get_instance_private (native);
GList *l;
for (l = meta_backend_get_gpus (priv->backend); l; l = l->next)
{
MetaGpu *gpu = l->data;
GList *l_crtc;
for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next)
{
MetaCrtcKms *crtc_kms = META_CRTC_KMS (l_crtc->data);
CrtcCursorData *crtc_cursor_data;
crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms);
crtc_cursor_data->hw_state_invalidated = TRUE;
}
}
priv->hw_state_invalidated = TRUE;
meta_cursor_renderer_force_update (renderer); meta_cursor_renderer_force_update (renderer);
} }
@ -1863,7 +1821,6 @@ meta_cursor_renderer_native_new (MetaBackend *backend,
G_CALLBACK (on_gpu_added_for_cursor), NULL); G_CALLBACK (on_gpu_added_for_cursor), NULL);
priv->backend = backend; priv->backend = backend;
priv->hw_state_invalidated = TRUE;
init_hw_cursor_support (cursor_renderer_native); init_hw_cursor_support (cursor_renderer_native);

View File

@ -33,6 +33,9 @@ G_DECLARE_FINAL_TYPE (MetaCursorRendererNative, meta_cursor_renderer_native,
META, CURSOR_RENDERER_NATIVE, META, CURSOR_RENDERER_NATIVE,
MetaCursorRenderer) MetaCursorRenderer)
void meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native,
MetaRendererView *view);
MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend, MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend,
ClutterInputDevice *device); ClutterInputDevice *device);

View File

@ -2345,12 +2345,6 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
return NULL; return NULL;
} }
gboolean
meta_renderer_native_is_mode_set_pending (MetaRendererNative *renderer_native)
{
return renderer_native->pending_mode_set;
}
gboolean gboolean
meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
uint32_t drm_format, uint32_t drm_format,
@ -3286,9 +3280,76 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer)
meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer)); meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer));
} }
void static void
meta_renderer_native_finish_frame (MetaRendererNative *renderer_native) add_onscreen_frame_info (MetaCrtc *crtc)
{ {
MetaGpu *gpu = meta_crtc_get_gpu (crtc);
MetaBackend *backend = meta_gpu_get_backend (gpu);
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
MetaStageNative *stage_native =
meta_clutter_backend_native_get_stage_native (clutter_backend);
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaRendererView *view = meta_renderer_get_view_for_crtc (renderer, crtc);
clutter_stage_cogl_add_onscreen_frame_info (CLUTTER_STAGE_COGL (stage_native),
CLUTTER_STAGE_VIEW (view));
}
void
meta_renderer_native_finish_frame (MetaRendererNative *renderer_native,
MetaRendererView *view,
ClutterFrame *frame)
{
MetaRenderer *renderer = META_RENDERER (renderer_native);
MetaBackend *backend = meta_renderer_get_backend (renderer);
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
if (!clutter_frame_has_result (frame))
{
MetaCrtc *crtc = meta_renderer_view_get_crtc (view);
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);;
MetaKmsUpdateFlag flags;
MetaKmsUpdate *kms_update;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
const GError *error;
kms_update = meta_kms_get_pending_update (kms, kms_device);
if (!kms_update)
{
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
return;
}
meta_kms_update_add_page_flip_listener (kms_update,
kms_crtc,
&page_flip_listener_vtable,
g_object_ref (view));
flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms,
kms_device,
flags);
switch (meta_kms_feedback_get_result (kms_feedback))
{
case META_KMS_FEEDBACK_PASSED:
add_onscreen_frame_info (crtc);
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
break;
case META_KMS_FEEDBACK_FAILED:
clutter_frame_set_result (frame,
CLUTTER_FRAME_RESULT_IDLE);
error = meta_kms_feedback_get_error (kms_feedback);
if (!g_error_matches (error,
G_IO_ERROR,
G_IO_ERROR_PERMISSION_DENIED))
g_warning ("Failed to post KMS update: %s", error->message);
break;
}
}
} }
static gboolean static gboolean

View File

@ -53,14 +53,14 @@ struct gbm_device * meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms);
MetaGpuKms * meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_native); MetaGpuKms * meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_native);
void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native); void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native,
MetaRendererView *view,
ClutterFrame *frame);
void meta_renderer_native_reset_modes (MetaRendererNative *renderer_native); void meta_renderer_native_reset_modes (MetaRendererNative *renderer_native);
gboolean meta_renderer_native_use_modifiers (MetaRendererNative *renderer_native); gboolean meta_renderer_native_use_modifiers (MetaRendererNative *renderer_native);
gboolean meta_renderer_native_is_mode_set_pending (MetaRendererNative *renderer_native);
gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
uint32_t drm_format, uint32_t drm_format,
uint64_t drm_modifier, uint64_t drm_modifier,

View File

@ -27,6 +27,7 @@
#include "backends/native/meta-stage-native.h" #include "backends/native/meta-stage-native.h"
#include "backends/meta-backend-private.h" #include "backends/meta-backend-private.h"
#include "backends/native/meta-cursor-renderer-native.h"
#include "backends/native/meta-renderer-native.h" #include "backends/native/meta-renderer-native.h"
#include "meta/meta-backend.h" #include "meta/meta-backend.h"
#include "meta/meta-monitor-manager.h" #include "meta/meta-monitor-manager.h"
@ -105,6 +106,21 @@ meta_stage_native_get_views (ClutterStageWindow *stage_window)
return meta_renderer_get_views (renderer); return meta_renderer_get_views (renderer);
} }
static void
meta_stage_native_prepare_frame (ClutterStageWindow *stage_window,
ClutterStageView *stage_view,
ClutterFrame *frame)
{
MetaBackend *backend = meta_get_backend ();
MetaCursorRenderer *cursor_renderer =
meta_backend_get_cursor_renderer (backend);
MetaCursorRendererNative *cursor_renderer_native =
META_CURSOR_RENDERER_NATIVE (cursor_renderer);
meta_cursor_renderer_native_prepare_frame (cursor_renderer_native,
META_RENDERER_VIEW (stage_view));
}
static void static void
meta_stage_native_finish_frame (ClutterStageWindow *stage_window, meta_stage_native_finish_frame (ClutterStageWindow *stage_window,
ClutterStageView *stage_view, ClutterStageView *stage_view,
@ -113,10 +129,9 @@ meta_stage_native_finish_frame (ClutterStageWindow *stage_window,
MetaBackend *backend = meta_get_backend (); MetaBackend *backend = meta_get_backend ();
MetaRenderer *renderer = meta_backend_get_renderer (backend); MetaRenderer *renderer = meta_backend_get_renderer (backend);
meta_renderer_native_finish_frame (META_RENDERER_NATIVE (renderer)); meta_renderer_native_finish_frame (META_RENDERER_NATIVE (renderer),
META_RENDERER_VIEW (stage_view),
if (!clutter_frame_has_result (frame)) frame);
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
} }
static void static void
@ -139,5 +154,6 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
iface->can_clip_redraws = meta_stage_native_can_clip_redraws; iface->can_clip_redraws = meta_stage_native_can_clip_redraws;
iface->get_geometry = meta_stage_native_get_geometry; iface->get_geometry = meta_stage_native_get_geometry;
iface->get_views = meta_stage_native_get_views; iface->get_views = meta_stage_native_get_views;
iface->prepare_frame = meta_stage_native_prepare_frame;
iface->finish_frame = meta_stage_native_finish_frame; iface->finish_frame = meta_stage_native_finish_frame;
} }