Merge branch 'this-is-not-the-firth-of-forth-bridge' into 'main'

Gate yet more repaint work behind dirty flags

See merge request wayland/weston!1892
This commit is contained in:
Daniel Stone 2025-12-19 18:42:17 +00:00
commit 033b50ccd5
19 changed files with 214 additions and 185 deletions

View file

@ -1047,7 +1047,6 @@ shared_output_create(struct weston_output *output, struct screen_share *ss, int
so->frame_listener.notify = shared_output_repainted;
wl_signal_add(&output->frame_signal, &so->frame_listener);
weston_output_disable_planes_incr(output);
weston_output_damage(output);
wl_list_insert(&ss->output_list, &so->output_link);

View file

@ -217,10 +217,6 @@ enum weston_hdcp_protection {
* \ingroup testharness
*/
struct weston_testsuite_quirks {
/** Force GL/Vulkan-renderer to do a full upload of wl_shm buffers. */
bool force_full_upload;
/** Ensure GL shadow fb is used, and always repaint it fully. */
bool gl_force_full_redraw_of_shadow_fb;
/** Force GL-renderer to use the internal YUV->RGB shader */
bool gl_force_import_yuv_fallback;
/** Required enum weston_capability bit mask, otherwise skip run. */

View file

@ -4365,8 +4365,6 @@ recorder_binding(struct weston_keyboard *keyboard, const struct timespec *time,
wl_signal_add(&output->base.frame_signal,
&output->recorder_frame_listener);
weston_output_schedule_repaint(&output->base);
weston_log("[libva recorder] initialized\n");
} else {
recorder_destroy(output);

View file

@ -119,6 +119,9 @@ static bool
weston_view_is_fully_blended(struct weston_view *ev,
pixman_region32_t *region);
static bool
weston_view_is_fully_transparent(struct weston_view *ev);
static void
weston_view_dirty_paint_nodes(struct weston_view *view)
{
@ -210,57 +213,47 @@ paint_node_update_early(struct weston_paint_node *pnode)
bool view_dirty = pnode->status & WESTON_PAINT_NODE_VIEW_DIRTY;
bool output_dirty = pnode->status & WESTON_PAINT_NODE_OUTPUT_DIRTY;
bool buffer_dirty = pnode->status & WESTON_PAINT_NODE_BUFFER_DIRTY;
bool recording_censor, unprotected_censor;
struct weston_buffer *buffer;
bool params_dirty =
pnode->status & WESTON_PAINT_NODE_BUFFER_PARAMS_DIRTY;
struct weston_buffer *buffer = surface->buffer_ref.buffer;
if (view_dirty || output_dirty) {
weston_view_buffer_to_output_matrix(pnode->view,
pnode->output, mat);
weston_matrix_invert(&pnode->output_to_buffer_matrix, mat);
pnode->needs_filtering = weston_matrix_needs_filtering(mat);
pnode->valid_transform = weston_matrix_to_transform(mat,
&pnode->transform);
pnode->is_fully_opaque = weston_view_is_opaque(pnode->view,
&pnode->view->transform.boundingbox);
pnode->is_fully_blended = weston_view_is_fully_blended(pnode->view,
&pnode->view->transform.boundingbox);
}
buffer = pnode->surface->buffer_ref.buffer;
pnode->draw_solid = false;
pnode->is_fully_transparent = false;
pnode->censored = false;
if (buffer->type == WESTON_BUFFER_SOLID) {
pnode->draw_solid = true;
pnode->is_fully_opaque = (pnode->view->alpha == 1.0f &&
buffer->solid.a == 1.0f);
pnode->is_fully_blended = !pnode->is_fully_opaque;
pnode->solid = buffer->solid;
if (pnode->solid.a == 0.0f)
pnode->is_fully_transparent = true;
}
if (pnode->view->alpha == 0.0f)
pnode->is_fully_transparent = true;
/* Check for 2 types of censor requirements
* - recording_censor: Censor protected view when a
* protected view is captured.
* - unprotected_censor: Censor regions of protected views
* when displayed on an output which has lower protection capability.
*/
recording_censor = (output->disable_planes > 0) &&
(surface->desired_protection > WESTON_HDCP_DISABLE);
unprotected_censor = (surface->desired_protection > output->current_protection);
if (surface->protection_mode ==
WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
(recording_censor || unprotected_censor)) {
pnode->draw_solid = true;
pnode->censored = true;
pnode->is_fully_opaque = (pnode->view->alpha == 1.0f);
pnode->is_fully_blended = !pnode->is_fully_opaque;
get_placeholder_color(pnode, &pnode->solid);
if (view_dirty || params_dirty) {
if (surface->protection_mode ==
WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
surface->desired_protection > output->current_protection) {
pnode->draw_solid = true;
pnode->censored = true;
pnode->is_fully_opaque =
(pnode->view->alpha == 1.0f);
pnode->is_fully_blended = !pnode->is_fully_opaque;
pnode->is_fully_transparent =
(pnode->view->alpha == 0.0f);
get_placeholder_color(pnode, &pnode->solid);
} else if (buffer->type == WESTON_BUFFER_SOLID) {
pnode->draw_solid = true;
pnode->solid = buffer->solid;
} else {
pnode->draw_solid = false;
pnode->censored = false;
pnode->is_fully_opaque =
weston_view_is_opaque(pnode->view,
&pnode->view->transform.boundingbox);
pnode->is_fully_blended =
weston_view_is_fully_blended(pnode->view,
&pnode->view->transform.boundingbox);
pnode->is_fully_transparent =
weston_view_is_fully_transparent(pnode->view);
}
}
if (buffer_dirty)
@ -1354,6 +1347,9 @@ weston_surface_compute_protection(struct protected_surface *psurface)
if (!min_protection_valid)
min_protection = WESTON_HDCP_DISABLE;
if (surface->current_protection == min_protection)
return;
surface->current_protection = min_protection;
weston_protected_surface_send_event(psurface, surface->current_protection);
@ -2309,6 +2305,24 @@ weston_view_is_fully_blended(struct weston_view *ev, pixman_region32_t *region)
return !pixman_region32_not_empty(&ev->transform.opaque);
}
static bool
weston_view_is_fully_transparent(struct weston_view *ev)
{
struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
if (ev->alpha == 0.0)
return true;
/* Well, we're not going to draw anything. */
if (!buffer)
return true;
if (buffer->type == WESTON_BUFFER_SOLID && buffer->solid.a == 0.0)
return true;
return false;
}
/** Check if the view has a valid buffer available
*
* @param ev The view to check if it has a valid buffer.
@ -3692,7 +3706,6 @@ weston_output_repaint(struct weston_output *output)
struct wl_list frame_callback_list;
int r;
uint32_t frame_time_msec;
enum weston_hdcp_protection highest_requested = WESTON_HDCP_DISABLE;
weston_output_latch(output);
@ -3720,30 +3733,15 @@ weston_output_repaint(struct weston_output *output)
assert(pnode->output == output);
}
/* Find the highest protection desired for an output */
wl_list_for_each(pnode, &output->paint_node_z_order_list,
z_order_link) {
/*
* The desired_protection of the output should be the
* maximum of the desired_protection of the surfaces,
* that are displayed on that output, to avoid
* reducing the protection for existing surfaces.
*/
if (pnode->surface->desired_protection > highest_requested)
highest_requested = pnode->surface->desired_protection;
}
/* If we're changing our protection characteristics, we need to go
* through a full repaint. */
if (output->desired_protection != highest_requested)
output->full_repaint_needed = true;
output->desired_protection = highest_requested;
wl_list_for_each(pnode, &output->paint_node_z_order_list,
z_order_link)
paint_node_update_early(pnode);
output_update_visibility(output);
if (output->paint_node_changes &
(WESTON_PAINT_NODE_VIEW_DIRTY | WESTON_PAINT_NODE_OUTPUT_DIRTY |
WESTON_PAINT_NODE_BUFFER_PARAMS_DIRTY)) {
output_update_visibility(output);
}
output_assign_planes(output);
@ -6518,7 +6516,7 @@ weston_output_iterate_heads(struct weston_output *output,
return container_of(node, struct weston_head, output_link);
}
static void
void
weston_output_compute_protection(struct weston_output *output)
{
struct weston_head *head;
@ -6526,6 +6524,12 @@ weston_output_compute_protection(struct weston_output *output)
bool op_protection_valid = false;
struct weston_compositor *wc = output->compositor;
if (output->disable_planes > 0 ||
weston_output_has_any_capture_tasks(output)) {
op_protection = WESTON_HDCP_DISABLE;
op_protection_valid = true;
}
wl_list_for_each(head, &output->head_list, output_link) {
if (!op_protection_valid) {
op_protection = head->current_protection;
@ -6539,9 +6543,18 @@ weston_output_compute_protection(struct weston_output *output)
op_protection = WESTON_HDCP_DISABLE;
if (output->current_protection != op_protection) {
struct weston_paint_node *pnode;
output->current_protection = op_protection;
weston_output_damage(output);
weston_schedule_surface_protection_update(wc);
wl_list_for_each(pnode, &output->paint_node_list,
output_link) {
if (pnode->view->surface->desired_protection >
WESTON_HDCP_DISABLE)
pnode->status |= WESTON_PAINT_NODE_VIEW_DIRTY;
}
}
}
@ -10712,6 +10725,7 @@ WL_EXPORT void
weston_output_disable_planes_incr(struct weston_output *output)
{
output->disable_planes++;
/*
* If disable_planes changes from 0 to non-zero, it means some type of
* recording of content has started, and therefore protection level of
@ -10720,12 +10734,16 @@ weston_output_disable_planes_incr(struct weston_output *output)
*/
if (output->disable_planes == 1)
weston_schedule_surface_protection_update(output->compositor);
weston_output_compute_protection(output);
weston_output_damage(output);
}
WL_EXPORT void
weston_output_disable_planes_decr(struct weston_output *output)
{
output->disable_planes--;
/*
* If disable_planes changes from non-zero to 0, it means no content
* recording is going on any more, and the protected and surfaces can be
@ -10734,6 +10752,8 @@ weston_output_disable_planes_decr(struct weston_output *output)
if (output->disable_planes == 0)
weston_schedule_surface_protection_update(output->compositor);
weston_output_compute_protection(output);
weston_output_damage(output);
}
/** Tell the renderer that the target framebuffer size has changed

View file

@ -391,6 +391,9 @@ weston_output_disable_planes_incr(struct weston_output *output);
void
weston_output_disable_planes_decr(struct weston_output *output);
void
weston_output_compute_protection(struct weston_output *output);
void
weston_output_set_single_mode(struct weston_output *output,
struct weston_mode *target);

View file

@ -394,6 +394,9 @@ weston_capture_task_destroy(struct weston_capture_task *ct)
ct->owner->pending = NULL;
wl_list_remove(&ct->link);
wl_list_remove(&ct->buffer_resource_destroy_listener.link);
weston_output_compute_protection(ct->owner->output);
free(ct);
}
@ -432,6 +435,8 @@ weston_capture_task_create(struct weston_capture_source *csrc,
if (ct->owner->pixel_source != WESTON_OUTPUT_CAPTURE_SOURCE_WRITEBACK)
weston_output_disable_planes_incr(ct->owner->output);
weston_output_compute_protection(ct->owner->output);
wl_signal_init(&ct->destroy_signal);
return ct;
@ -532,6 +537,15 @@ weston_output_pull_capture_task(struct weston_output *output,
return NULL;
}
/** Check if any capture tasks are waiting on the output */
WL_EXPORT bool
weston_output_has_any_capture_tasks(struct weston_output *output)
{
struct weston_output_capture_info *ci = output->capture_info;
return ci && !wl_list_empty(&ci->pending_capture_list);
}
/** Check if any renderer-based capture tasks are waiting on the output */
WL_EXPORT bool
weston_output_has_renderer_capture_tasks(struct weston_output *output)
@ -645,7 +659,6 @@ weston_capture_source_v1_capture(struct wl_client *client,
}
csrc->pending = weston_capture_task_create(csrc, buffer);
weston_output_schedule_repaint(csrc->output);
}
static const struct weston_capture_source_v1_interface weston_capture_source_v1_impl = {

View file

@ -69,6 +69,8 @@ weston_output_update_capture_info(struct weston_output *output,
const struct pixel_format_info *format,
const struct weston_drm_format_array *writeback_formats);
bool
weston_output_has_any_capture_tasks(struct weston_output *output);
bool
weston_output_has_renderer_capture_tasks(struct weston_output *output);

View file

@ -2289,24 +2289,22 @@ draw_paint_node(struct weston_paint_node *pnode,
&pnode->view->geometry.scissor);
pixman_region32_subtract(&surface_blend, &surface_blend,
&surface_opaque);
transform_damage(pnode, &repaint, &quads, &nquads);
if (pixman_region32_not_empty(&surface_opaque)) {
transform_damage(pnode, &repaint, &quads, &nquads);
repaint_region(gr, pnode, quads, nquads, &surface_opaque,
&sconf, true);
gs->used_in_output_repaint = true;
}
if (pixman_region32_not_empty(&surface_blend)) {
transform_damage(pnode, &repaint, &quads, &nquads);
repaint_region(gr, pnode, quads, nquads, &surface_blend, &sconf,
false);
gs->used_in_output_repaint = true;
}
if (quads)
free(quads);
gs->used_in_output_repaint = true;
pixman_region32_fini(&surface_blend);
pixman_region32_fini(&surface_opaque);
@ -2802,10 +2800,7 @@ gl_renderer_repaint_output(struct weston_output *output,
if (shadow_exists(go)) {
/* Repaint into shadow. */
if (compositor->test_data.test_quirks.gl_force_full_redraw_of_shadow_fb)
repaint_views(output, &output->region);
else
repaint_views(output, output_damage);
repaint_views(output, output_damage);
glBindFramebuffer(GL_FRAMEBUFFER, rb->fb);
glViewport(go->area.x, area_y,
@ -2947,8 +2942,6 @@ gl_renderer_flush_damage(struct weston_paint_node *pnode)
{
struct weston_surface *surface = pnode->surface;
struct gl_renderer *gr = get_renderer(surface->compositor);
const struct weston_testsuite_quirks *quirks =
&surface->compositor->test_data.test_quirks;
struct weston_buffer *buffer = surface->buffer_ref.buffer;
struct gl_surface_state *gs = get_surface_state(surface);
struct gl_buffer_state *gb = gs->buffer;
@ -2976,7 +2969,7 @@ gl_renderer_flush_damage(struct weston_paint_node *pnode)
data = wl_shm_buffer_get_data(buffer->shm_buffer);
if (gb->needs_full_upload || quirks->force_full_upload) {
if (gb->needs_full_upload) {
wl_shm_buffer_begin_access(buffer->shm_buffer);
for (j = 0; j < gb->num_textures; j++) {
@ -4419,13 +4412,10 @@ gl_renderer_output_create(struct weston_output *output,
{
struct gl_output_state *go;
struct gl_renderer *gr = get_renderer(output->compositor);
const struct weston_testsuite_quirks *quirks;
int i;
assert(!get_output_state(output));
quirks = &output->compositor->test_data.test_quirks;
go = zalloc(sizeof *go);
if (go == NULL)
return -1;
@ -4448,9 +4438,8 @@ gl_renderer_output_create(struct weston_output *output,
go->render_sync = EGL_NO_SYNC_KHR;
if ((output->color_outcome->from_blend_to_output != NULL &&
output->from_blend_to_output_by_backend == false) ||
quirks->gl_force_full_redraw_of_shadow_fb) {
if (output->color_outcome->from_blend_to_output != NULL &&
output->from_blend_to_output_by_backend == false) {
assert(gl_features_has(gr, FEATURE_COLOR_TRANSFORMS));
go->shadow_format =

View file

@ -2840,8 +2840,6 @@ vulkan_renderer_flush_damage(struct weston_paint_node *pnode)
struct vulkan_renderer *vr = get_renderer(ec);
struct weston_surface *surface = pnode->surface;
const struct weston_testsuite_quirks *quirks =
&surface->compositor->test_data.test_quirks;
struct weston_buffer *buffer = surface->buffer_ref.buffer;
struct vulkan_surface_state *vs = get_surface_state(surface);
struct vulkan_buffer_state *vb = vs->buffer;
@ -2872,7 +2870,7 @@ vulkan_renderer_flush_damage(struct weston_paint_node *pnode)
data = wl_shm_buffer_get_data(buffer->shm_buffer);
if (vb->needs_full_upload || quirks->force_full_upload) {
if (vb->needs_full_upload) {
wl_shm_buffer_begin_access(buffer->shm_buffer);
for (int j = 0; j < vb->num_textures; j++) {

View file

@ -233,7 +233,6 @@ weston_screenshooter_shoot(struct weston_output *output,
wl_signal_add(&buffer->destroy_signal, &l->buffer_destroy_listener);
weston_output_disable_planes_incr(output);
weston_output_schedule_repaint(output);
return 0;
}
@ -477,7 +476,6 @@ weston_recorder_create(struct weston_output *output, const char *filename)
recorder->frame_listener.notify = weston_recorder_frame_notify;
wl_signal_add(&output->frame_signal, &recorder->frame_listener);
weston_output_disable_planes_incr(output);
weston_output_damage(output);
return recorder;

View file

@ -314,6 +314,25 @@ apply_damage_buffer(pixman_region32_t *dest,
pixman_region32_fini(&buffer_damage);
}
static void
output_update_desired_protection(struct weston_output *output)
{
struct weston_paint_node *pnode;
enum weston_hdcp_protection protection = WESTON_HDCP_DISABLE;
wl_list_for_each(pnode, &output->paint_node_z_order_list,
z_order_link) {
if (pnode->surface->desired_protection > protection)
protection = pnode->surface->desired_protection;
}
if (protection == output->desired_protection)
return;
output->desired_protection = protection;
weston_output_damage(output);
}
static void
weston_surface_set_desired_protection(struct weston_surface *surface,
enum weston_hdcp_protection protection)
@ -325,9 +344,12 @@ weston_surface_set_desired_protection(struct weston_surface *surface,
surface->desired_protection = protection;
weston_surface_dirty_paint_nodes(surface,
WESTON_PAINT_NODE_VIEW_DIRTY);
wl_list_for_each(pnode, &surface->paint_node_list, surface_link) {
if (pixman_region32_not_empty(&pnode->visible))
weston_output_damage(pnode->output);
output_update_desired_protection(pnode->output);
}
}
@ -338,7 +360,14 @@ weston_surface_set_protection_mode(struct weston_surface *surface,
struct content_protection *cp = surface->compositor->content_protection;
struct protected_surface *psurface;
if (surface->protection_mode == p_mode)
return;
surface->protection_mode = p_mode;
weston_surface_dirty_paint_nodes(surface,
WESTON_PAINT_NODE_VIEW_DIRTY);
wl_list_for_each(psurface, &cp->protected_list, link) {
if (!psurface || psurface->surface != surface)
continue;
@ -451,6 +480,9 @@ weston_surface_apply_state(struct weston_surface *surface,
weston_view_geometry_dirty_internal(view);
weston_view_update_transform(view);
}
weston_surface_dirty_paint_nodes(surface,
WESTON_PAINT_NODE_VIEW_DIRTY);
}
pixman_region32_fini(&opaque);

View file

@ -54,20 +54,6 @@ fixture_setup(struct weston_test_harness *harness)
}
DECLARE_FIXTURE_SETUP(fixture_setup);
#define DECLARE_LIST_ITERATOR(name, parent, list, child, link) \
static child * \
next_##name(parent *from, child *pos) \
{ \
struct wl_list *entry = pos ? &pos->link : &from->list; \
child *ret = wl_container_of(entry->next, ret, link); \
return (&ret->link == &from->list) ? NULL : ret; \
}
DECLARE_LIST_ITERATOR(pnode_from_z, struct weston_output, paint_node_z_order_list,
struct weston_paint_node, z_order_link);
DECLARE_LIST_ITERATOR(view_from_surface, struct weston_surface, views,
struct weston_view, link);
static void
assert_surface_is_background(struct wet_testsuite_data *suite_data,

View file

@ -61,18 +61,6 @@ fixture_setup(struct weston_test_harness *harness)
}
DECLARE_FIXTURE_SETUP(fixture_setup);
#define DECLARE_LIST_ITERATOR(name, parent, list, child, link) \
static child * \
next_##name(parent *from, child *pos) \
{ \
struct wl_list *entry = pos ? &pos->link : &from->list; \
child *ret = wl_container_of(entry->next, ret, link); \
return (&ret->link == &from->list) ? NULL : ret; \
}
DECLARE_LIST_ITERATOR(pnode_from_z, struct weston_output, paint_node_z_order_list,
struct weston_paint_node, z_order_link);
TEST(four_apps_in_a_square)
{
struct wet_testsuite_data *suite_data = TEST_GET_SUITE_DATA();

View file

@ -106,48 +106,7 @@ fixture_setup(struct weston_test_harness *harness, const struct setup_args *arg)
setup.shell = SHELL_TEST_DESKTOP;
setup.refresh = HIGHEST_OUTPUT_REFRESH;
/*
* The test here works by swapping the whole wl_surface into a
* different color but lying that there is only a small damage area.
* Then the test checks that only the damage area gets the new color
* on screen.
*
* The following quirk forces GL-renderer and Vulkan-renderer to update
* the whole texture even for partial damage. Otherwise, they would
* only copy the damaged area from the wl_shm buffer into a texture.
*
* Those output_damage tests where the surface is scaled up by the
* compositor will use bilinear texture sampling due to the policy
* in the renderers.
*
* Pixman renderer never makes copies of wl_shm buffers, so bilinear
* sampling there will always produce the expected result. However,
* with GL-renderer and Vulkan-renderer if the texture is not updated
* beyond the strict damage region, bilinear sampling will result in a
* blend of the old and new colors at the edges of the damage
* rectangles. This blend would be detrimental to testing the damage
* regions and would cause test failures due to reference image
* mismatch. What we actually want to see is the crisp outline of the
* damage rectangles.
*/
setup.test_quirks.force_full_upload = true;
if (arg->gl_shadow_fb) {
/*
* A second case for GL-renderer: the shadow framebuffer
*
* This tests blit_shadow_to_output() specifically. The quirk
* forces the shadow framebuffer to be redrawn completely, which
* means the test surface will be completely filled with a new
* color regardless of damage. The blit uses damage too, and
* the damage pattern that is tested for needs to appear in
* that step.
*
* The quirk also ensures the shadow framebuffer is created
* even if not needed.
*/
setup.test_quirks.gl_force_full_redraw_of_shadow_fb = true;
/* To skip instead of fail the test if shadow not available */
setup.test_quirks.required_capabilities = WESTON_CAP_COLOR_OPS;
}
@ -156,6 +115,38 @@ fixture_setup(struct weston_test_harness *harness, const struct setup_args *arg)
}
DECLARE_FIXTURE_SETUP_WITH_ARG(fixture_setup, my_setup_args, meta);
static void
verify_damage(struct client *client, struct wet_testsuite_data *suite_data,
struct rectangle expected, int offset_x, int offset_y)
{
RUN_INSIDE_BREAKPOINT(client, suite_data) {
struct weston_compositor *compositor = breakpoint->compositor;
struct weston_output *output = next_output(compositor, NULL);
pixman_region32_t *damage = breakpoint->data;
pixman_box32_t *extents = pixman_region32_extents(damage);
int x1 = MAX(expected.x + offset_x, 0);
int y1 = MAX(expected.y + offset_y, 0);
int x2 = MIN(x1 + expected.width, output->width);
int y2 = MIN(y1 + expected.height, output->height);
testlog("have (%d, %d) -> (%d, %d); wanted to see (%d, %d) -> (%d, %d)\n",
extents->x1, extents->y1, extents->x2, extents->y2,
expected.x + offset_x, expected.y + offset_y,
expected.x + offset_x + expected.width,
expected.y + offset_y + expected.height);
test_assert_enum(breakpoint->template_->breakpoint,
WESTON_TEST_BREAKPOINT_POST_REPAINT);
assert_output_matches(suite_data, output, client->output);
test_assert_int_eq(pixman_region32_n_rects(damage), 1);
test_assert_int_eq(extents->x1, x1);
test_assert_int_eq(extents->y1, y1);
test_assert_int_eq(extents->x2, x2);
test_assert_int_eq(extents->y2, y2);
}
}
static void
commit_buffer_with_damage(struct surface *surface,
struct buffer *buffer,
@ -177,6 +168,7 @@ commit_buffer_with_damage(struct surface *surface,
TEST(output_damage)
{
#define COUNT_BUFS 3
struct wet_testsuite_data *suite_data = TEST_GET_SUITE_DATA();
const struct setup_args *oargs;
struct client *client;
bool match = true;
@ -221,11 +213,11 @@ TEST(output_damage)
* should color just the box on the output.
*/
for (i = 1; i < COUNT_BUFS; i++) {
client_push_breakpoint(client, suite_data,
WESTON_TEST_BREAKPOINT_POST_REPAINT,
(struct wl_proxy *) client->output->wl_output);
commit_buffer_with_damage(client->surface, buf[i], damages[i]);
if (!verify_screen_content(client, refname, i, NULL, i, NULL,
NO_DECORATIONS)) {
match = false;
}
verify_damage(client, suite_data, damages[i], 19, 19);
}
test_assert_true(match);

View file

@ -65,21 +65,6 @@ surface_commit_color(struct client *client, struct wl_surface *surface,
return buf;
}
#define DECLARE_LIST_ITERATOR(name, parent, list, child, link) \
static child * \
next_##name(parent *from, child *pos) \
{ \
struct wl_list *entry = pos ? &pos->link : &from->list; \
if (entry->next == &from->list) \
return NULL; \
return container_of(entry->next, child, link); \
}
DECLARE_LIST_ITERATOR(output, struct weston_compositor, output_list,
struct weston_output, link);
DECLARE_LIST_ITERATOR(pnode_from_z, struct weston_output, paint_node_z_order_list,
struct weston_paint_node, z_order_link);
static enum weston_paint_node_status
get_paint_node_status(struct client *client,
struct wet_testsuite_data *suite_data)

View file

@ -2579,8 +2579,15 @@ assert_output_matches(struct wet_testsuite_data *suite_data,
}
test_assert_true(found_client_resource);
test_assert_s32_eq(s->width, c->width);
test_assert_s32_eq(s->height, c->height);
if (!(s->transform & 1)) {
/* unrotated */
test_assert_s32_eq(s->width, c->width / s->current_scale);
test_assert_s32_eq(s->height, c->height / s->current_scale);
} else {
/* rotated */
test_assert_s32_eq(s->width, c->height / s->current_scale);
test_assert_s32_eq(s->height, c->width / s->current_scale);
}
}
/**

View file

@ -44,6 +44,7 @@
#include "viewporter-client-protocol.h"
#include "weston-output-capture-client-protocol.h"
#include "xdg-shell-client-protocol.h"
#include "libweston-internal.h"
#include "weston-testsuite-data.h"
#include "fifo-v1-client-protocol.h"
#include "commit-timing-v1-client-protocol.h"
@ -399,6 +400,24 @@ color_rgb888(pixman_color_t *tmp, uint8_t r, uint8_t g, uint8_t b);
/* Specifies that the currently-executing breakpoint should be rearmed */
#define REARM_BREAKPOINT(breakpoint_) breakpoint_->rearm_on_release = true
#define DECLARE_LIST_ITERATOR(name, parent, list, child, link) \
static inline child * \
next_##name(parent *from, child *pos) \
{ \
struct wl_list *entry = pos ? &pos->link : &from->list; \
if (entry->next == &from->list) \
return NULL; \
return container_of(entry->next, child, link); \
}
DECLARE_LIST_ITERATOR(output, struct weston_compositor, output_list,
struct weston_output, link);
DECLARE_LIST_ITERATOR(pnode_from_z, struct weston_output, paint_node_z_order_list,
struct weston_paint_node, z_order_link);
DECLARE_LIST_ITERATOR(view_from_surface, struct weston_surface, views,
struct weston_view, link);
void
client_push_breakpoint(struct client *client,
struct wet_testsuite_data *suite_data,

View file

@ -90,7 +90,8 @@ struct weston_test_output {
static void
maybe_breakpoint(struct weston_test *test,
enum weston_test_breakpoint breakpoint,
void *resource)
void *resource,
void *data)
{
struct wet_test_pending_breakpoint *bp, *tmp;
struct wet_testsuite_data *tsd = weston_compositor_get_test_data(test->compositor);
@ -113,6 +114,7 @@ maybe_breakpoint(struct weston_test *test,
active_bp->compositor = test->compositor;
active_bp->resource = resource;
active_bp->template_ = bp;
active_bp->data = data;
/* Wake the client with the active breakpoint, and wait for it
* to return control */
@ -135,7 +137,7 @@ output_repaint_listener(struct wl_listener *listener, void *data)
wl_list_for_each(head, &to->output->head_list, output_link) {
maybe_breakpoint(to->test, WESTON_TEST_BREAKPOINT_POST_REPAINT,
head);
head, data);
}
}

View file

@ -117,6 +117,8 @@ struct wet_test_active_breakpoint {
struct weston_compositor *compositor;
/** type-specific pointer to resource which triggered this breakpoint */
void *resource;
/** type-specific pointer to further data for this invocation */
void *data;
/** on release, reinsert the template to trigger next time */
bool rearm_on_release;
/** client's original breakpoint request */