kms: Allow passing framebuffer damage metadata

This commit adds support to atomic KMS backend for optional plane property
prop_fb_damage_clips. Some drivers (e.g. EVDI) take advantage of this
property and process only updated regions of the screen instead of
processing the full frame. This can save system resources.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1879>
This commit is contained in:
Piotr Lopatka 2021-09-03 19:39:12 +01:00
parent 7555688d8d
commit af0460d0ce
6 changed files with 80 additions and 0 deletions

View File

@ -416,6 +416,8 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
MetaKmsPlaneAssignment *plane_assignment = update_entry;
MetaKmsPlane *plane = plane_assignment->plane;
MetaDrmBuffer *buffer;
MetaKmsFbDamage *fb_damage;
uint32_t prop_id;
buffer = plane_assignment->buffer;
@ -539,6 +541,32 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
return FALSE;
}
fb_damage = plane_assignment->fb_damage;
if (fb_damage &&
meta_kms_plane_get_prop_id (plane,
META_KMS_PLANE_PROP_FB_DAMAGE_CLIPS_ID))
{
meta_topic (META_DEBUG_KMS,
"[atomic] Setting %d damage clips on %u",
fb_damage->n_rects,
meta_kms_plane_get_id (plane));
prop_id = store_new_blob (impl_device,
blob_ids,
fb_damage->rects,
fb_damage->n_rects *
sizeof (struct drm_mode_rect),
error);
if (!prop_id)
return FALSE;
if (!add_plane_property (impl_device,
plane, req,
META_KMS_PLANE_PROP_FB_DAMAGE_CLIPS_ID,
prop_id,
error))
return FALSE;
}
return TRUE;
}

View File

@ -41,6 +41,7 @@ typedef enum _MetaKmsPlaneProp
META_KMS_PLANE_PROP_CRTC_H,
META_KMS_PLANE_PROP_FB_ID,
META_KMS_PLANE_PROP_CRTC_ID,
META_KMS_PLANE_PROP_FB_DAMAGE_CLIPS_ID,
META_KMS_PLANE_N_PROPS
} MetaKmsPlaneProp;

View File

@ -446,6 +446,11 @@ init_properties (MetaKmsPlane *plane,
.name = "CRTC_ID",
.type = DRM_MODE_PROP_OBJECT,
},
[META_KMS_PLANE_PROP_FB_DAMAGE_CLIPS_ID] =
{
.name = "FB_DAMAGE_CLIPS",
.type = DRM_MODE_PROP_BLOB,
},
}
};

View File

@ -34,6 +34,12 @@ typedef struct _MetaKmsFeedback
GError *error;
} MetaKmsFeedback;
typedef struct _MetaKmsFbDamage
{
struct drm_mode_rect *rects;
int n_rects;
} MetaKmsFbDamage;
typedef struct _MetaKmsPlaneAssignment
{
MetaKmsUpdate *update;
@ -43,6 +49,7 @@ typedef struct _MetaKmsPlaneAssignment
MetaFixed16Rectangle src_rect;
MetaRectangle dst_rect;
MetaKmsAssignPlaneFlag flags;
MetaKmsFbDamage *fb_damage;
uint64_t rotation;

View File

@ -129,9 +129,17 @@ meta_kms_feedback_get_error (const MetaKmsFeedback *feedback)
return feedback->error;
}
static void
meta_kms_fb_damage_free (MetaKmsFbDamage *fb_damage)
{
g_free (fb_damage->rects);
g_free (fb_damage);
}
static void
meta_kms_plane_assignment_free (MetaKmsPlaneAssignment *plane_assignment)
{
g_clear_pointer (&plane_assignment->fb_damage, meta_kms_fb_damage_free);
g_free (plane_assignment);
}
@ -456,6 +464,33 @@ meta_kms_update_set_custom_page_flip (MetaKmsUpdate *update,
update->custom_page_flip = custom_page_flip;
}
void
meta_kms_plane_assignment_set_fb_damage (MetaKmsPlaneAssignment *plane_assignment,
const int *rectangles,
int n_rectangles)
{
MetaKmsFbDamage *fb_damage;
struct drm_mode_rect *mode_rects;
int i;
mode_rects = g_new0 (struct drm_mode_rect, n_rectangles);
for (i = 0; i < n_rectangles; ++i)
{
mode_rects[i].x1 = rectangles[i * 4];
mode_rects[i].y1 = rectangles[i * 4 + 1];
mode_rects[i].x2 = mode_rects[i].x1 + rectangles[i * 4 + 2];
mode_rects[i].y2 = mode_rects[i].y1 + rectangles[i * 4 + 3];
}
fb_damage = g_new0 (MetaKmsFbDamage, 1);
*fb_damage = (MetaKmsFbDamage) {
.rects = mode_rects,
.n_rects = n_rectangles,
};
plane_assignment->fb_damage = fb_damage;
}
void
meta_kms_plane_assignment_set_rotation (MetaKmsPlaneAssignment *plane_assignment,
uint64_t rotation)

View File

@ -115,6 +115,10 @@ void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
const uint16_t *green,
const uint16_t *blue);
void meta_kms_plane_assignment_set_fb_damage (MetaKmsPlaneAssignment *plane_assignment,
const int *rectangles,
int n_rectangles);
MetaKmsPlaneAssignment * meta_kms_update_assign_plane (MetaKmsUpdate *update,
MetaKmsCrtc *crtc,
MetaKmsPlane *plane,