mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
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:
parent
487ea0dd95
commit
c985753442
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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__ */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user