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;
_clutter_stage_window_prepare_frame (stage_window, view, &frame);
if (clutter_stage_view_has_redraw_clip (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);
}
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
_clutter_stage_window_finish_frame (ClutterStageWindow *window,
ClutterStageView *view,

View File

@ -52,6 +52,9 @@ struct _ClutterStageWindowInterface
GList *(* get_views) (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,
ClutterStageView *view,
ClutterFrame *frame);
@ -89,6 +92,10 @@ gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWin
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,
ClutterStageView *view,
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);
}
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
clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
{

View File

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

View File

@ -1948,6 +1948,28 @@ meta_monitor_mode_foreach_output (MetaMonitor *monitor,
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 *
meta_monitor_get_display_name (MetaMonitor *monitor)
{

View File

@ -264,6 +264,10 @@ gboolean meta_monitor_mode_foreach_output (MetaMonitor *monitor,
gpointer user_data,
GError **error);
MetaMonitorCrtcMode * meta_monitor_get_crtc_mode_for_output (MetaMonitor *monitor,
MetaMonitorMode *mode,
MetaOutput *output);
META_EXPORT_TEST
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
{
MetaDrmBuffer *buffer;
gboolean needs_sync_position;
gboolean hw_state_invalidated;
} CrtcCursorData;
struct _MetaCursorRendererNative
@ -91,7 +93,6 @@ struct _MetaCursorRendererNativePrivate
{
MetaBackend *backend;
gboolean hw_state_invalidated;
gboolean has_hw_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);
static void
on_kms_update_result (const MetaKmsFeedback *kms_feedback,
gpointer user_data);
static void
realize_cursor_sprite (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite,
@ -266,6 +271,7 @@ ensure_crtc_cursor_data (MetaCrtcKms *crtc_kms)
if (!crtc_cursor_data)
{
crtc_cursor_data = g_new0 (CrtcCursorData, 1);
crtc_cursor_data->hw_state_invalidated = TRUE;
meta_crtc_kms_set_cursor_renderer_private (crtc_kms,
crtc_cursor_data,
g_free);
@ -275,15 +281,12 @@ ensure_crtc_cursor_data (MetaCrtcKms *crtc_kms)
}
static void
set_crtc_cursor (MetaCursorRendererNative *native,
MetaKmsUpdate *kms_update,
MetaCrtcKms *crtc_kms,
int x,
int y,
MetaCursorSprite *cursor_sprite)
assign_cursor_plane (MetaCursorRendererNative *native,
MetaCrtcKms *crtc_kms,
int x,
int y,
MetaCursorSprite *cursor_sprite)
{
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
MetaCrtc *crtc = META_CRTC (crtc_kms);
MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite);
MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
@ -303,6 +306,7 @@ set_crtc_cursor (MetaCursorRendererNative *native,
CrtcCursorData *crtc_cursor_data;
int cursor_hotspot_x;
int cursor_hotspot_y;
MetaKmsUpdate *kms_update;
MetaKmsPlaneAssignment *plane_assignment;
if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET)
@ -333,9 +337,12 @@ set_crtc_cursor (MetaCursorRendererNative *native,
flags = META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL;
crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms);
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;
kms_update =
meta_kms_ensure_pending_update (meta_kms_device_get_kms (kms_device),
meta_kms_crtc_get_device (kms_crtc));
plane_assignment = meta_kms_update_assign_plane (kms_update,
kms_crtc,
cursor_plane,
@ -351,6 +358,10 @@ set_crtc_cursor (MetaCursorRendererNative *native,
cursor_hotspot_x,
cursor_hotspot_y);
meta_kms_update_add_result_listener (kms_update,
on_kms_update_result,
native);
crtc_cursor_data->buffer = buffer;
if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET)
@ -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
calculate_cursor_crtc_sprite_scale (MetaCursorSprite *cursor_sprite,
MetaLogicalMonitor *logical_monitor)
@ -405,139 +387,121 @@ 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;
MetaLogicalMonitor *in_logical_monitor;
graphene_rect_t in_local_cursor_rect;
MetaCursorSprite *in_cursor_sprite;
gboolean out_painted;
} UpdateCrtcCursorData;
static gboolean
update_monitor_crtc_cursor (MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
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;
MetaCursorRenderer *cursor_renderer =
META_CURSOR_RENDERER (cursor_renderer_native);
MetaOutput *output = meta_crtc_get_outputs (crtc)->data;
MetaMonitor *monitor = meta_output_get_monitor (output);
MetaLogicalMonitor *logical_monitor =
meta_monitor_get_logical_monitor (monitor);
const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
graphene_rect_t rect;
graphene_rect_t local_crtc_rect;
graphene_rect_t local_cursor_rect;
float view_scale;
float crtc_cursor_x, crtc_cursor_y;
CoglTexture *texture;
int tex_width, tex_height;
float cursor_crtc_scale;
MetaRectangle cursor_rect;
MetaMonitorTransform transform;
MetaMonitorTransform inverted_transform;
MetaMonitorMode *monitor_mode;
MetaMonitorCrtcMode *monitor_crtc_mode;
const MetaCrtcModeInfo *crtc_mode_info;
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;
view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view));
transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
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);
meta_monitor_calculate_crtc_pos (monitor, monitor_mode,
monitor_crtc_mode->output,
transform,
&crtc_x, &crtc_y);
local_crtc_rect = crtc_config->layout;
graphene_rect_offset (&local_crtc_rect,
-logical_monitor->rect.x,
-logical_monitor->rect.y);
crtc_mode_info = meta_crtc_mode_get_info (monitor_crtc_mode->crtc_mode);
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;
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;
}
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
tex_width = cogl_texture_get_width (texture);
tex_height = cogl_texture_get_height (texture);
scaled_crtc_rect = (graphene_rect_t) {
.origin = {
.x = crtc_x / scale,
.y = crtc_y / scale
},
.size = {
.width = crtc_width / scale,
.height = crtc_height / scale
},
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)
};
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);
transform = meta_logical_monitor_get_transform (logical_monitor);
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
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 cursor_crtc_scale;
int tex_width, tex_height;
inverted_transform = meta_monitor_transform_invert (transform);
crtc_cursor_x = (data->in_local_cursor_rect.origin.x -
scaled_crtc_rect.origin.x) * scale;
crtc_cursor_y = (data->in_local_cursor_rect.origin.y -
scaled_crtc_rect.origin.y) * scale;
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);
texture = meta_cursor_sprite_get_cogl_texture (data->in_cursor_sprite);
tex_width = cogl_texture_get_width (texture);
tex_height = cogl_texture_get_height (texture);
cursor_crtc_scale =
calculate_cursor_crtc_sprite_scale (data->in_cursor_sprite,
data->in_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)
};
inverted_transform = meta_monitor_transform_invert (transform);
meta_rectangle_transform (&cursor_rect,
inverted_transform,
crtc_mode_info->width,
crtc_mode_info->height,
&cursor_rect);
set_crtc_cursor (data->in_cursor_renderer_native,
kms_update,
assign_cursor_plane (cursor_renderer_native,
META_CRTC_KMS (crtc),
cursor_rect.x,
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)
{
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)
{
unset_crtc_cursor (data->in_cursor_renderer_native,
kms_update,
META_CRTC_KMS (crtc));
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
@ -556,68 +520,61 @@ disable_hw_cursor_for_crtc (MetaKmsCrtc *kms_crtc,
cursor_renderer_gpu_data->hw_cursor_broken = TRUE;
}
static void
update_hw_cursor (MetaCursorRendererNative *native,
MetaCursorSprite *cursor_sprite)
void
meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native,
MetaRendererView *view)
{
MetaCursorRenderer *cursor_renderer =
META_CURSOR_RENDERER (cursor_renderer_native);
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
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 rect;
gboolean painted = FALSE;
MetaCrtc *crtc = meta_renderer_view_get_crtc (view);
MetaCursorSprite *cursor_sprite;
graphene_rect_t cursor_rect;
cairo_rectangle_int_t view_layout;
graphene_rect_t view_rect;
CrtcCursorData *crtc_cursor_data;
if (cursor_sprite)
rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
else
rect = GRAPHENE_RECT_INIT_ZERO;
if (meta_monitor_manager_get_power_save_mode (monitor_manager) !=
META_POWER_SAVE_ON)
return;
logical_monitors =
meta_monitor_manager_get_logical_monitors (monitor_manager);
for (l = logical_monitors; l; l = l->next)
{
MetaLogicalMonitor *logical_monitor = l->data;
UpdateCrtcCursorData data;
GList *monitors;
GList *k;
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;
data = (UpdateCrtcCursorData) {
.in_cursor_renderer_native = native,
.in_logical_monitor = logical_monitor,
.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,
};
cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
if (!cursor_sprite)
goto unset_cursor;
monitors = meta_logical_monitor_get_monitors (logical_monitor);
for (k = monitors; k; k = k->next)
{
MetaMonitor *monitor = k->data;
MetaMonitorMode *monitor_mode;
if (!priv->has_hw_cursor)
goto unset_cursor;
monitor_mode = meta_monitor_get_current_mode (monitor);
meta_monitor_mode_foreach_crtc (monitor, monitor_mode,
update_monitor_crtc_cursor,
&data,
NULL);
}
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;
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)
meta_cursor_renderer_emit_painted (renderer, cursor_sprite);
crtc_cursor_data->needs_sync_position = FALSE;
crtc_cursor_data->hw_state_invalidated = FALSE;
return;
unset_cursor:
unset_crtc_cursor (cursor_renderer_native, crtc);
crtc_cursor_data = ensure_crtc_cursor_data (META_CRTC_KMS (crtc));
crtc_cursor_data->hw_state_invalidated = FALSE;
}
static gboolean
@ -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
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
MetaCursorSprite *cursor_sprite)
@ -1081,10 +1061,7 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
MetaRendererNative *renderer_native =
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);
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (priv->backend));
g_autoptr (GList) gpus = NULL;
if (cursor_sprite)
@ -1097,43 +1074,9 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite);
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))
{
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);
}
}
schedule_sync_position (native);
clutter_stage_schedule_update (stage);
return (priv->has_hw_cursor ||
!cursor_sprite ||
@ -1779,8 +1722,23 @@ force_update_hw_cursor (MetaCursorRendererNative *native)
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
MetaCursorRendererNativePrivate *priv =
meta_cursor_renderer_native_get_instance_private (native);
GList *l;
for (l = meta_backend_get_gpus (priv->backend); l; l = l->next)
{
MetaGpu *gpu = l->data;
GList *l_crtc;
for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next)
{
MetaCrtcKms *crtc_kms = META_CRTC_KMS (l_crtc->data);
CrtcCursorData *crtc_cursor_data;
crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms);
crtc_cursor_data->hw_state_invalidated = TRUE;
}
}
priv->hw_state_invalidated = TRUE;
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);
priv->backend = backend;
priv->hw_state_invalidated = TRUE;
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,
MetaCursorRenderer)
void meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native,
MetaRendererView *view);
MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend,
ClutterInputDevice *device);

View File

@ -2345,12 +2345,6 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
return NULL;
}
gboolean
meta_renderer_native_is_mode_set_pending (MetaRendererNative *renderer_native)
{
return renderer_native->pending_mode_set;
}
gboolean
meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
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));
}
void
meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
static void
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

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);
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);
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,
uint32_t drm_format,
uint64_t drm_modifier,

View File

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