kms/update: Add API to merge two updates
This is intended to be used only for plane assignment, and CRTC like changes, so that one can e.g. change a cursor plane on a pending update that changes the primary plane, before it has been committed to KMS. The kms-updates test overrides the get-state function MetaKmsCrtc. This is needd to not have the update mechanism not clamp the gamma size to 0, as vkms reports the gamma length 0. By pretending it's 3, we can test a simple and small gamma lut is merged correctly when merging updates. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2854>
This commit is contained in:
parent
3e3611d171
commit
9dcb28ffd1
@ -94,6 +94,7 @@ void meta_crtc_set_gamma_lut (MetaCrtc *crtc,
|
||||
META_EXPORT_TEST
|
||||
void meta_gamma_lut_free (MetaGammaLut *lut);
|
||||
|
||||
META_EXPORT_TEST
|
||||
MetaGammaLut * meta_gamma_lut_new (int size,
|
||||
const uint16_t *red,
|
||||
const uint16_t *green,
|
||||
|
@ -181,6 +181,10 @@ void meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update,
|
||||
|
||||
GList * meta_kms_update_take_result_listeners (MetaKmsUpdate *update);
|
||||
|
||||
META_EXPORT_TEST
|
||||
void meta_kms_update_merge_from (MetaKmsUpdate *update,
|
||||
MetaKmsUpdate *other_update);
|
||||
|
||||
void meta_kms_result_listener_notify (MetaKmsResultListener *listener,
|
||||
const MetaKmsFeedback *feedback);
|
||||
|
||||
|
@ -671,6 +671,154 @@ meta_kms_custom_page_flip_free (MetaKmsCustomPageFlip *custom_page_flip)
|
||||
g_free (custom_page_flip);
|
||||
}
|
||||
|
||||
static GList *
|
||||
find_plane_assignment_link_for (MetaKmsUpdate *update,
|
||||
MetaKmsPlane *plane)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = update->plane_assignments; l; l = l->next)
|
||||
{
|
||||
MetaKmsPlaneAssignment *plane_assignment = l->data;
|
||||
|
||||
if (plane_assignment->plane == plane)
|
||||
return l;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
merge_plane_assignments_from (MetaKmsUpdate *update,
|
||||
MetaKmsUpdate *other_update)
|
||||
{
|
||||
while (other_update->plane_assignments)
|
||||
{
|
||||
GList *l = other_update->plane_assignments;
|
||||
MetaKmsPlaneAssignment *other_plane_assignment = l->data;
|
||||
MetaKmsPlane *plane = other_plane_assignment->plane;
|
||||
GList *el;
|
||||
|
||||
other_update->plane_assignments =
|
||||
g_list_remove_link (other_update->plane_assignments, l);
|
||||
|
||||
el = find_plane_assignment_link_for (update, plane);
|
||||
if (el)
|
||||
{
|
||||
meta_kms_plane_assignment_free (el->data);
|
||||
update->plane_assignments =
|
||||
g_list_insert_before_link (update->plane_assignments, el, l);
|
||||
update->plane_assignments =
|
||||
g_list_delete_link (update->plane_assignments, el);
|
||||
}
|
||||
else
|
||||
{
|
||||
update->plane_assignments =
|
||||
g_list_insert_before_link (update->plane_assignments,
|
||||
update->plane_assignments,
|
||||
l);
|
||||
}
|
||||
other_plane_assignment->update = update;
|
||||
}
|
||||
}
|
||||
|
||||
static GList *
|
||||
find_color_update_link_for (MetaKmsUpdate *update,
|
||||
MetaKmsCrtc *crtc)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = update->crtc_color_updates; l; l = l->next)
|
||||
{
|
||||
MetaKmsCrtcColorUpdate *color_update = l->data;
|
||||
|
||||
if (color_update->crtc == crtc)
|
||||
return l;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
merge_crtc_color_updates_from (MetaKmsUpdate *update,
|
||||
MetaKmsUpdate *other_update)
|
||||
{
|
||||
while (other_update->crtc_color_updates)
|
||||
{
|
||||
GList *l = other_update->crtc_color_updates;
|
||||
MetaKmsCrtcColorUpdate *other_crtc_color_update = l->data;
|
||||
MetaKmsCrtc *crtc = other_crtc_color_update->crtc;
|
||||
GList *el;
|
||||
|
||||
other_update->crtc_color_updates =
|
||||
g_list_remove_link (other_update->crtc_color_updates, l);
|
||||
|
||||
el = find_color_update_link_for (update, crtc);
|
||||
if (el)
|
||||
{
|
||||
meta_kms_crtc_color_updates_free (el->data);
|
||||
update->crtc_color_updates =
|
||||
g_list_insert_before_link (update->crtc_color_updates, el, l);
|
||||
update->crtc_color_updates =
|
||||
g_list_delete_link (update->crtc_color_updates, el);
|
||||
}
|
||||
else
|
||||
{
|
||||
update->crtc_color_updates =
|
||||
g_list_insert_before_link (update->crtc_color_updates,
|
||||
update->crtc_color_updates,
|
||||
l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
merge_custom_page_flip_from (MetaKmsUpdate *update,
|
||||
MetaKmsUpdate *other_update)
|
||||
{
|
||||
g_warn_if_fail ((!update->custom_page_flip &&
|
||||
!other_update->custom_page_flip) ||
|
||||
((!!update->custom_page_flip) ^
|
||||
(!!other_update->custom_page_flip)));
|
||||
|
||||
g_clear_pointer (&update->custom_page_flip, meta_kms_custom_page_flip_free);
|
||||
update->custom_page_flip = g_steal_pointer (&other_update->custom_page_flip);
|
||||
}
|
||||
|
||||
static void
|
||||
merge_page_flip_listeners_from (MetaKmsUpdate *update,
|
||||
MetaKmsUpdate *other_update)
|
||||
{
|
||||
update->page_flip_listeners =
|
||||
g_list_concat (update->page_flip_listeners,
|
||||
g_steal_pointer (&other_update->page_flip_listeners));
|
||||
}
|
||||
|
||||
static void
|
||||
merge_result_listeners_from (MetaKmsUpdate *update,
|
||||
MetaKmsUpdate *other_update)
|
||||
{
|
||||
update->result_listeners =
|
||||
g_list_concat (update->result_listeners,
|
||||
g_steal_pointer (&other_update->result_listeners));
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_update_merge_from (MetaKmsUpdate *update,
|
||||
MetaKmsUpdate *other_update)
|
||||
{
|
||||
g_return_if_fail (update->device == other_update->device);
|
||||
g_return_if_fail (!update->mode_sets && !other_update->mode_sets);
|
||||
g_return_if_fail (!update->connector_updates &&
|
||||
!other_update->connector_updates);
|
||||
|
||||
merge_plane_assignments_from (update, other_update);
|
||||
merge_crtc_color_updates_from (update, other_update);
|
||||
merge_custom_page_flip_from (update, other_update);
|
||||
merge_page_flip_listeners_from (update, other_update);
|
||||
merge_result_listeners_from (update, other_update);
|
||||
}
|
||||
|
||||
MetaKmsUpdate *
|
||||
meta_kms_update_new (MetaKmsDevice *device)
|
||||
{
|
||||
|
@ -121,6 +121,7 @@ void meta_kms_update_mode_set (MetaKmsUpdate *update,
|
||||
GList *connectors,
|
||||
MetaKmsMode *mode);
|
||||
|
||||
META_EXPORT_TEST
|
||||
void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
|
||||
MetaKmsCrtc *crtc,
|
||||
const MetaGammaLut *gamma);
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "backends/native/meta-kms-connector.h"
|
||||
#include "backends/native/meta-kms-crtc.h"
|
||||
#include "backends/native/meta-kms-device.h"
|
||||
@ -31,6 +33,27 @@
|
||||
|
||||
static MetaContext *test_context;
|
||||
|
||||
const MetaKmsCrtcState *
|
||||
meta_kms_crtc_get_current_state (MetaKmsCrtc *crtc)
|
||||
{
|
||||
static MetaKmsCrtcState mock_state;
|
||||
static const MetaKmsCrtcState *
|
||||
(* real_get_current_state) (MetaKmsCrtc *crtc) = NULL;
|
||||
const MetaKmsCrtcState *state;
|
||||
|
||||
if (!real_get_current_state)
|
||||
real_get_current_state = dlsym (RTLD_NEXT, __func__);
|
||||
|
||||
state = real_get_current_state (crtc);
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
mock_state = *state;
|
||||
mock_state.gamma.size = 3;
|
||||
|
||||
return &mock_state;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_kms_update_sanity (void)
|
||||
{
|
||||
@ -368,6 +391,170 @@ meta_test_kms_update_page_flip (void)
|
||||
g_main_loop_unref (data.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_kms_update_merge (void)
|
||||
{
|
||||
MetaKmsDevice *device;
|
||||
MetaKmsUpdate *update1;
|
||||
MetaKmsCrtc *crtc;
|
||||
MetaKmsConnector *connector;
|
||||
MetaKmsPlane *primary_plane;
|
||||
MetaKmsPlane *cursor_plane;
|
||||
MetaKmsMode *mode;
|
||||
int mode_width, mode_height;
|
||||
g_autoptr (MetaDrmBuffer) primary_buffer1 = NULL;
|
||||
g_autoptr (MetaDrmBuffer) cursor_buffer1 = NULL;
|
||||
MetaKmsPlaneAssignment *cursor_plane_assignment;
|
||||
MetaKmsUpdate *update2;
|
||||
g_autoptr (MetaGammaLut) lut = NULL;
|
||||
g_autoptr (MetaDrmBuffer) cursor_buffer2 = NULL;
|
||||
GList *plane_assignments;
|
||||
MetaKmsPlaneAssignment *plane_assignment;
|
||||
GList *crtc_color_updates;
|
||||
MetaKmsCrtcColorUpdate *crtc_color_update;
|
||||
MetaGammaLut *crtc_gamma;
|
||||
|
||||
device = meta_get_test_kms_device (test_context);
|
||||
crtc = meta_get_test_kms_crtc (device);
|
||||
connector = meta_get_test_kms_connector (device);
|
||||
primary_plane = meta_kms_device_get_primary_plane_for (device, crtc);
|
||||
cursor_plane = meta_kms_device_get_cursor_plane_for (device, crtc);
|
||||
|
||||
mode = meta_kms_connector_get_preferred_mode (connector);
|
||||
|
||||
/*
|
||||
* Create an update1 with buffer 1 on the primary plane, and cursor buffer 1
|
||||
* on the cursor plane at at (24, 48)
|
||||
*/
|
||||
|
||||
update1 = meta_kms_update_new (device);
|
||||
|
||||
mode_width = meta_kms_mode_get_width (mode);
|
||||
mode_height = meta_kms_mode_get_height (mode);
|
||||
primary_buffer1 = meta_create_test_mode_dumb_buffer (device, mode);
|
||||
|
||||
meta_kms_update_assign_plane (update1,
|
||||
crtc,
|
||||
primary_plane,
|
||||
primary_buffer1,
|
||||
meta_get_mode_fixed_rect_16 (mode),
|
||||
meta_get_mode_rect (mode),
|
||||
META_KMS_ASSIGN_PLANE_FLAG_NONE);
|
||||
|
||||
cursor_buffer1 = meta_create_test_dumb_buffer (device, 64, 64);
|
||||
|
||||
cursor_plane_assignment =
|
||||
meta_kms_update_assign_plane (update1,
|
||||
crtc,
|
||||
cursor_plane,
|
||||
cursor_buffer1,
|
||||
META_FIXED_16_RECTANGLE_INIT_INT (0, 0,
|
||||
64, 64),
|
||||
META_RECTANGLE_INIT (24, 48, 64, 64),
|
||||
META_KMS_ASSIGN_PLANE_FLAG_NONE);
|
||||
meta_kms_plane_assignment_set_cursor_hotspot (cursor_plane_assignment,
|
||||
10, 11);
|
||||
|
||||
/*
|
||||
* Create an update2 with with cursor buffer 2
|
||||
* on the cursor plane at at (32, 56), and a new CRTC gamma.
|
||||
*/
|
||||
|
||||
update2 = meta_kms_update_new (device);
|
||||
|
||||
lut = meta_gamma_lut_new (3,
|
||||
(uint16_t[]) { 1, 2, 3 },
|
||||
(uint16_t[]) { 4, 5, 6 },
|
||||
(uint16_t[]) { 7, 8, 9 });
|
||||
meta_kms_update_set_crtc_gamma (update2, crtc, lut);
|
||||
|
||||
cursor_buffer2 = meta_create_test_dumb_buffer (device, 64, 64);
|
||||
cursor_plane_assignment =
|
||||
meta_kms_update_assign_plane (update2,
|
||||
crtc,
|
||||
cursor_plane,
|
||||
cursor_buffer2,
|
||||
META_FIXED_16_RECTANGLE_INIT_INT (0, 0,
|
||||
64, 64),
|
||||
META_RECTANGLE_INIT (32, 56, 64, 64),
|
||||
META_KMS_ASSIGN_PLANE_FLAG_NONE);
|
||||
meta_kms_plane_assignment_set_cursor_hotspot (cursor_plane_assignment,
|
||||
9, 7);
|
||||
|
||||
/*
|
||||
* Merge and check result.
|
||||
*/
|
||||
|
||||
meta_kms_update_merge_from (update1, update2);
|
||||
meta_kms_update_free (update2);
|
||||
|
||||
plane_assignments = meta_kms_update_get_plane_assignments (update1);
|
||||
g_assert_cmpuint (g_list_length (plane_assignments), ==, 2);
|
||||
plane_assignment = meta_kms_update_get_primary_plane_assignment (update1,
|
||||
crtc);
|
||||
g_assert_nonnull (plane_assignment);
|
||||
g_assert (plane_assignment->update == update1);
|
||||
g_assert (plane_assignment->crtc == crtc);
|
||||
g_assert (plane_assignment->plane == primary_plane);
|
||||
g_assert (plane_assignment->buffer == primary_buffer1);
|
||||
g_assert_false (plane_assignment->cursor_hotspot.is_valid);
|
||||
g_assert_cmpint (plane_assignment->src_rect.x, ==, 0);
|
||||
g_assert_cmpint (plane_assignment->src_rect.y, ==, 0);
|
||||
g_assert_cmpint (plane_assignment->src_rect.width,
|
||||
==,
|
||||
meta_fixed_16_from_int (mode_width));
|
||||
g_assert_cmpint (plane_assignment->src_rect.height,
|
||||
==,
|
||||
meta_fixed_16_from_int (mode_height));
|
||||
g_assert_cmpint (plane_assignment->dst_rect.x, ==, 0);
|
||||
g_assert_cmpint (plane_assignment->dst_rect.y, ==, 0);
|
||||
g_assert_cmpint (plane_assignment->dst_rect.width, ==, mode_width);
|
||||
g_assert_cmpint (plane_assignment->dst_rect.height, ==, mode_height);
|
||||
|
||||
plane_assignment = meta_kms_update_get_cursor_plane_assignment (update1,
|
||||
crtc);
|
||||
g_assert_nonnull (plane_assignment);
|
||||
g_assert (plane_assignment->update == update1);
|
||||
g_assert (plane_assignment->crtc == crtc);
|
||||
g_assert (plane_assignment->plane == cursor_plane);
|
||||
g_assert (plane_assignment->buffer == META_DRM_BUFFER (cursor_buffer2));
|
||||
g_assert_true (plane_assignment->cursor_hotspot.is_valid);
|
||||
g_assert_cmpint (plane_assignment->cursor_hotspot.x, ==, 9);
|
||||
g_assert_cmpint (plane_assignment->cursor_hotspot.y, ==, 7);
|
||||
g_assert_cmpint (plane_assignment->src_rect.x, ==, 0);
|
||||
g_assert_cmpint (plane_assignment->src_rect.y, ==, 0);
|
||||
g_assert_cmpint (plane_assignment->src_rect.width,
|
||||
==,
|
||||
meta_fixed_16_from_int (64));
|
||||
g_assert_cmpint (plane_assignment->src_rect.height,
|
||||
==,
|
||||
meta_fixed_16_from_int (64));
|
||||
g_assert_cmpint (plane_assignment->dst_rect.x, ==, 32);
|
||||
g_assert_cmpint (plane_assignment->dst_rect.y, ==, 56);
|
||||
g_assert_cmpint (plane_assignment->dst_rect.width, ==, 64);
|
||||
g_assert_cmpint (plane_assignment->dst_rect.height, ==, 64);
|
||||
|
||||
crtc_color_updates = meta_kms_update_get_crtc_color_updates (update1);
|
||||
g_assert_cmpuint (g_list_length (crtc_color_updates), ==, 1);
|
||||
crtc_color_update = crtc_color_updates->data;
|
||||
crtc_gamma = crtc_color_update->gamma.state;
|
||||
g_assert_nonnull (crtc_gamma);
|
||||
|
||||
g_assert_nonnull (crtc_gamma);
|
||||
g_assert_cmpint (crtc_gamma->size, ==, 3);
|
||||
g_assert_cmpuint (crtc_gamma->red[0], ==, 1);
|
||||
g_assert_cmpuint (crtc_gamma->red[1], ==, 2);
|
||||
g_assert_cmpuint (crtc_gamma->red[2], ==, 3);
|
||||
g_assert_cmpuint (crtc_gamma->green[0], ==, 4);
|
||||
g_assert_cmpuint (crtc_gamma->green[1], ==, 5);
|
||||
g_assert_cmpuint (crtc_gamma->green[2], ==, 6);
|
||||
g_assert_cmpuint (crtc_gamma->blue[0], ==, 7);
|
||||
g_assert_cmpuint (crtc_gamma->blue[1], ==, 8);
|
||||
g_assert_cmpuint (crtc_gamma->blue[2], ==, 9);
|
||||
|
||||
meta_kms_update_free (update1);
|
||||
}
|
||||
|
||||
static void
|
||||
init_tests (void)
|
||||
{
|
||||
@ -381,6 +568,8 @@ init_tests (void)
|
||||
meta_test_kms_update_mode_sets);
|
||||
g_test_add_func ("/backends/native/kms/update/page-flip",
|
||||
meta_test_kms_update_page_flip);
|
||||
g_test_add_func ("/backends/native/kms/update/merge",
|
||||
meta_test_kms_update_merge);
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user