mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2025-12-20 04:40:07 +01:00
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:
commit
033b50ccd5
19 changed files with 214 additions and 185 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue