kms/impl-simple: Add cursor plane processing
A cursor plane can now be assigned, and for the simple KMS implementation, it'll translate into drmModeSetCursor() and drmModeMoveCursor() calls. When assignments failed, the cursor planes that failed to be assigned are communicated via the feedback object. https://gitlab.gnome.org/GNOME/mutter/merge_requests/930
This commit is contained in:
parent
73dcb9fa22
commit
7c3172a0af
@ -747,11 +747,156 @@ process_entries (MetaKmsImpl *impl,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_cursor_plane_assignment (MetaKmsImpl *impl,
|
||||
MetaKmsUpdate *update,
|
||||
MetaKmsPlaneAssignment *plane_assignment,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsPlane *plane;
|
||||
MetaKmsDevice *device;
|
||||
MetaKmsImplDevice *impl_device;
|
||||
int fd;
|
||||
|
||||
plane = plane_assignment->plane;
|
||||
device = meta_kms_plane_get_device (plane);
|
||||
impl_device = meta_kms_device_get_impl_device (device);
|
||||
fd = meta_kms_impl_device_get_fd (impl_device);
|
||||
|
||||
if (!(plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED))
|
||||
{
|
||||
int width, height;
|
||||
int ret;
|
||||
|
||||
width = meta_fixed_16_to_int (plane_assignment->dst_rect.width);
|
||||
height = meta_fixed_16_to_int (plane_assignment->dst_rect.height);
|
||||
|
||||
ret = drmModeSetCursor (fd, meta_kms_crtc_get_id (plane_assignment->crtc),
|
||||
plane_assignment->fb_id,
|
||||
width, height);
|
||||
if (ret != 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
|
||||
"drmModeSetCursor failed: %s", g_strerror (-ret));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
drmModeMoveCursor (fd,
|
||||
meta_kms_crtc_get_id (plane_assignment->crtc),
|
||||
meta_fixed_16_to_int (plane_assignment->dst_rect.x),
|
||||
meta_fixed_16_to_int (plane_assignment->dst_rect.y));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_plane_assignment (MetaKmsImpl *impl,
|
||||
MetaKmsUpdate *update,
|
||||
MetaKmsPlaneAssignment *plane_assignment,
|
||||
MetaKmsPlaneFeedback **plane_feedback)
|
||||
{
|
||||
MetaKmsPlane *plane;
|
||||
MetaKmsPlaneType plane_type;
|
||||
GError *error = NULL;
|
||||
|
||||
plane = plane_assignment->plane;
|
||||
plane_type = meta_kms_plane_get_plane_type (plane);
|
||||
switch (plane_type)
|
||||
{
|
||||
case META_KMS_PLANE_TYPE_PRIMARY:
|
||||
/* Handled as part of the mode-set and page flip. */
|
||||
return TRUE;
|
||||
case META_KMS_PLANE_TYPE_CURSOR:
|
||||
if (!process_cursor_plane_assignment (impl, update,
|
||||
plane_assignment,
|
||||
&error))
|
||||
{
|
||||
*plane_feedback =
|
||||
meta_kms_plane_feedback_new_take_error (plane,
|
||||
plane_assignment->crtc,
|
||||
g_steal_pointer (&error));
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
case META_KMS_PLANE_TYPE_OVERLAY:
|
||||
error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Overlay planes cannot be assigned");
|
||||
*plane_feedback =
|
||||
meta_kms_plane_feedback_new_take_error (plane,
|
||||
plane_assignment->crtc,
|
||||
g_steal_pointer (&error));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static GList *
|
||||
process_plane_assignments (MetaKmsImpl *impl,
|
||||
MetaKmsUpdate *update)
|
||||
{
|
||||
GList *failed_planes = NULL;
|
||||
GList *l;
|
||||
|
||||
for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next)
|
||||
{
|
||||
MetaKmsPlaneAssignment *plane_assignment = l->data;
|
||||
MetaKmsPlaneFeedback *plane_feedback;
|
||||
|
||||
if (!process_plane_assignment (impl, update, plane_assignment,
|
||||
&plane_feedback))
|
||||
failed_planes = g_list_prepend (failed_planes, plane_feedback);
|
||||
}
|
||||
|
||||
return failed_planes;
|
||||
}
|
||||
|
||||
static GList *
|
||||
generate_all_failed_feedbacks (MetaKmsUpdate *update)
|
||||
{
|
||||
GList *failed_planes = NULL;
|
||||
GList *l;
|
||||
|
||||
for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next)
|
||||
{
|
||||
MetaKmsPlaneAssignment *plane_assignment = l->data;
|
||||
MetaKmsPlane *plane;
|
||||
MetaKmsPlaneType plane_type;
|
||||
MetaKmsPlaneFeedback *plane_feedback;
|
||||
|
||||
plane = plane_assignment->plane;
|
||||
plane_type = meta_kms_plane_get_plane_type (plane);
|
||||
switch (plane_type)
|
||||
{
|
||||
case META_KMS_PLANE_TYPE_PRIMARY:
|
||||
continue;
|
||||
case META_KMS_PLANE_TYPE_CURSOR:
|
||||
case META_KMS_PLANE_TYPE_OVERLAY:
|
||||
break;
|
||||
}
|
||||
|
||||
plane_feedback =
|
||||
meta_kms_plane_feedback_new_take_error (plane_assignment->plane,
|
||||
plane_assignment->crtc,
|
||||
g_error_new (G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"Discarded"));
|
||||
failed_planes = g_list_prepend (failed_planes, plane_feedback);
|
||||
}
|
||||
|
||||
return failed_planes;
|
||||
}
|
||||
|
||||
static MetaKmsFeedback *
|
||||
meta_kms_impl_simple_process_update (MetaKmsImpl *impl,
|
||||
MetaKmsUpdate *update)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GList *failed_planes;
|
||||
GList *l;
|
||||
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl));
|
||||
@ -761,32 +906,43 @@ meta_kms_impl_simple_process_update (MetaKmsImpl *impl,
|
||||
meta_kms_update_get_connector_properties (update),
|
||||
process_connector_property,
|
||||
&error))
|
||||
goto discard_page_flips;
|
||||
goto err_planes_not_assigned;
|
||||
|
||||
if (!process_entries (impl,
|
||||
update,
|
||||
meta_kms_update_get_mode_sets (update),
|
||||
process_mode_set,
|
||||
&error))
|
||||
goto discard_page_flips;
|
||||
goto err_planes_not_assigned;
|
||||
|
||||
if (!process_entries (impl,
|
||||
update,
|
||||
meta_kms_update_get_crtc_gammas (update),
|
||||
process_crtc_gamma,
|
||||
&error))
|
||||
goto discard_page_flips;
|
||||
goto err_planes_not_assigned;
|
||||
|
||||
failed_planes = process_plane_assignments (impl, update);
|
||||
if (failed_planes)
|
||||
{
|
||||
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Failed to assign one or more planes");
|
||||
goto err_planes_assigned;
|
||||
}
|
||||
|
||||
if (!process_entries (impl,
|
||||
update,
|
||||
meta_kms_update_get_page_flips (update),
|
||||
process_page_flip,
|
||||
&error))
|
||||
goto discard_page_flips;
|
||||
goto err_planes_assigned;
|
||||
|
||||
return meta_kms_feedback_new_passed ();
|
||||
|
||||
discard_page_flips:
|
||||
err_planes_not_assigned:
|
||||
failed_planes = generate_all_failed_feedbacks (update);
|
||||
|
||||
err_planes_assigned:
|
||||
for (l = meta_kms_update_get_page_flips (update); l; l = l->next)
|
||||
{
|
||||
MetaKmsPageFlip *page_flip = l->data;
|
||||
@ -794,7 +950,7 @@ discard_page_flips:
|
||||
discard_page_flip (impl, update, page_flip);
|
||||
}
|
||||
|
||||
return meta_kms_feedback_new_failed (error);
|
||||
return meta_kms_feedback_new_failed (failed_planes, error);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -30,6 +30,7 @@ typedef struct _MetaKmsFeedback
|
||||
{
|
||||
MetaKmsFeedbackResult result;
|
||||
|
||||
GList *failed_planes;
|
||||
GError *error;
|
||||
} MetaKmsFeedback;
|
||||
|
||||
@ -85,9 +86,16 @@ typedef struct _MetaKmsPageFlip
|
||||
gpointer custom_page_flip_user_data;
|
||||
} MetaKmsPageFlip;
|
||||
|
||||
void meta_kms_plane_feedback_free (MetaKmsPlaneFeedback *plane_feedback);
|
||||
|
||||
MetaKmsPlaneFeedback * meta_kms_plane_feedback_new_take_error (MetaKmsPlane *plane,
|
||||
MetaKmsCrtc *crtc,
|
||||
GError *error);
|
||||
|
||||
MetaKmsFeedback * meta_kms_feedback_new_passed (void);
|
||||
|
||||
MetaKmsFeedback * meta_kms_feedback_new_failed (GError *error);
|
||||
MetaKmsFeedback * meta_kms_feedback_new_failed (GList *failed_planes,
|
||||
GError *error);
|
||||
|
||||
void meta_kms_update_seal (MetaKmsUpdate *update);
|
||||
|
||||
@ -122,4 +130,7 @@ GList * meta_kms_update_get_connector_properties (MetaKmsUpdate *update);
|
||||
|
||||
GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsPlaneFeedback,
|
||||
meta_kms_plane_feedback_free)
|
||||
|
||||
#endif /* META_KMS_UPDATE_PRIVATE_H */
|
||||
|
@ -37,6 +37,30 @@ struct _MetaKmsUpdate
|
||||
GList *crtc_gammas;
|
||||
};
|
||||
|
||||
void
|
||||
meta_kms_plane_feedback_free (MetaKmsPlaneFeedback *plane_feedback)
|
||||
{
|
||||
g_error_free (plane_feedback->error);
|
||||
g_free (plane_feedback);
|
||||
}
|
||||
|
||||
MetaKmsPlaneFeedback *
|
||||
meta_kms_plane_feedback_new_take_error (MetaKmsPlane *plane,
|
||||
MetaKmsCrtc *crtc,
|
||||
GError *error)
|
||||
{
|
||||
MetaKmsPlaneFeedback *plane_feedback;
|
||||
|
||||
plane_feedback = g_new0 (MetaKmsPlaneFeedback, 1);
|
||||
*plane_feedback = (MetaKmsPlaneFeedback) {
|
||||
.plane = plane,
|
||||
.crtc = crtc,
|
||||
.error = error,
|
||||
};
|
||||
|
||||
return plane_feedback;
|
||||
}
|
||||
|
||||
MetaKmsFeedback *
|
||||
meta_kms_feedback_new_passed (void)
|
||||
{
|
||||
@ -51,7 +75,8 @@ meta_kms_feedback_new_passed (void)
|
||||
}
|
||||
|
||||
MetaKmsFeedback *
|
||||
meta_kms_feedback_new_failed (GError *error)
|
||||
meta_kms_feedback_new_failed (GList *failed_planes,
|
||||
GError *error)
|
||||
{
|
||||
MetaKmsFeedback *feedback;
|
||||
|
||||
@ -59,6 +84,7 @@ meta_kms_feedback_new_failed (GError *error)
|
||||
*feedback = (MetaKmsFeedback) {
|
||||
.result = META_KMS_FEEDBACK_FAILED,
|
||||
.error = error,
|
||||
.failed_planes = failed_planes,
|
||||
};
|
||||
|
||||
return feedback;
|
||||
@ -67,6 +93,8 @@ meta_kms_feedback_new_failed (GError *error)
|
||||
void
|
||||
meta_kms_feedback_free (MetaKmsFeedback *feedback)
|
||||
{
|
||||
g_list_free_full (feedback->failed_planes,
|
||||
(GDestroyNotify) meta_kms_plane_feedback_free);
|
||||
g_clear_error (&feedback->error);
|
||||
g_free (feedback);
|
||||
}
|
||||
@ -77,6 +105,12 @@ meta_kms_feedback_get_result (MetaKmsFeedback *feedback)
|
||||
return feedback->result;
|
||||
}
|
||||
|
||||
GList *
|
||||
meta_kms_feedback_get_failed_planes (MetaKmsFeedback *feedback)
|
||||
{
|
||||
return feedback->failed_planes;
|
||||
}
|
||||
|
||||
const GError *
|
||||
meta_kms_feedback_get_error (MetaKmsFeedback *feedback)
|
||||
{
|
||||
|
@ -38,6 +38,7 @@ typedef enum _MetaKmsFeedbackResult
|
||||
typedef enum _MetaKmsAssignPlaneFlag
|
||||
{
|
||||
META_KMS_ASSIGN_PLANE_FLAG_NONE = 0,
|
||||
META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED = 1 << 0,
|
||||
} MetaKmsAssignPlaneFlag;
|
||||
|
||||
struct _MetaKmsPageFlipFeedback
|
||||
@ -59,10 +60,19 @@ struct _MetaKmsPageFlipFeedback
|
||||
typedef int (* MetaKmsCustomPageFlipFunc) (gpointer custom_page_flip_data,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct _MetaKmsPlaneFeedback
|
||||
{
|
||||
MetaKmsPlane *plane;
|
||||
MetaKmsCrtc *crtc;
|
||||
GError *error;
|
||||
} MetaKmsPlaneFeedback;
|
||||
|
||||
void meta_kms_feedback_free (MetaKmsFeedback *feedback);
|
||||
|
||||
MetaKmsFeedbackResult meta_kms_feedback_get_result (MetaKmsFeedback *feedback);
|
||||
|
||||
GList * meta_kms_feedback_get_failed_planes (MetaKmsFeedback *feedback);
|
||||
|
||||
const GError * meta_kms_feedback_get_error (MetaKmsFeedback *feedback);
|
||||
|
||||
MetaKmsUpdate * meta_kms_update_new (void);
|
||||
|
Loading…
Reference in New Issue
Block a user