Compare commits

...

20 Commits
main ... 13.0

Author SHA1 Message Date
Marius Vlad
8cb33a1916 build: bump to version 13.0.3 for the point release
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-06-05 14:59:31 +03:00
Marius Vlad
86c636d817 build: bump to version 13.0.2 for the point release
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-06-05 13:20:15 +03:00
Pekka Paalanen
fc0419609e CI: work around LeakSanitizer crashes with use_tls=0
Without this fix, we have randomly been getting CI failures due to
LeakSanitizer itself crashing after all the tests in a program have
succeeded. This has been happening randomly for a long time, but
https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/1486
made it very reliably repeatable in the job x86_64-debian-full-build
(and no other job) in the test-subsurface-shot program.

--- Fixture 2 (GL) ok: passed 4, skipped 0, failed 0, total 4
Tracer caught signal 11: addr=0x1b8 pc=0x7f6b3ba640f0 sp=0x7f6b2cc77d10
==489==LeakSanitizer has encountered a fatal error.

I was also able to get a core file after twiddling, but there it ended
up with lsan aborting itself rather than a segfault.

We got some clues that use_tls=0 might work around this, from
https://github.com/google/sanitizers/issues/1342
https://github.com/google/sanitizers/issues/1409
and some other projects that have cargo-culted the same workaround.

Using that cause more false leaks to appear, so they need to be
suppressed. I suppose we are not interested in catching leaks in glib
using code, so I opted to suppress g_malloc0 altogether. Pinpointing it
better might have required much more slower stack tracing.

wl_shm_buffer_begin_access() uses TLS, so no wonder it gets flagged.

ld-*.so is simply uninteresting to us, and it got flagged too.

Since this might have been fixed already in LeakSanitizer upstream, who
knows, leave some notes to revisit this when we upgrade that in CI.

This fix seems to make the branch of
https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/1486
in my quick testing.

Suggested-by: Derek Foreman <derek.foreman@collabora.com>
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
(cherry picked from commit 3179e0f0e0)
2024-06-05 13:20:15 +03:00
Marius Vlad
fad928ca37 build: bump to version 13.0.1 for the point release
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
2024-04-23 18:26:12 +03:00
Marius Vlad
b0af40acc4 libweston: Add paint node destruction into weston_layer_entry_remove()
This prevents a potential crash where users of
weston_layer_entry_insert/layer_entry_remove() would see when moving
views into a NULL layer (effectively unmapping the surface/view).

Users that have migrated to the weston_view_move_to_layer() are immune
to this issue because that takes care of paint node destruction.

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
(cherry picked from commit 2d3cca3d3e)
2024-04-16 13:25:36 +03:00
Jeffy Chen
f0a396d479 desktop-shell: Avoid using maximized size in fullscreen state
The fullscreen should take precedence if the client requests both
window states at the same time.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
(cherry picked from commit 5dbf96fb6c)
2024-04-16 13:25:36 +03:00
Wujian Sun
5d58718bc5 libweston-desktop: Fix weston crash when lost the shsurf
The shell_surface may disappear when keyboard lost focus,
then the shsurf will be NULL.
Have an ahead check for shsurf before calling the callback
in weston_desktop_surface_foreach_child.

Fixes #811

Tested-by: Erkai Ji <erkai.ji@nxp.com>
Signed-off-by: Wujian Sun <wujian.sun_1@nxp.com>
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
(cherry picked from commit 042d02f422)
2024-04-16 13:25:36 +03:00
Robert Mader
f9cd0297f5 backend-drm: Sort planes by faked zpos
Just like we already do for planes with proper zpos. Otherwise we'll
often end up choosing the primary plane instead of an overlay one
in `drm_output_find_plane_for_view()`.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
(cherry picked from commit e34e027515)
2024-04-16 13:25:36 +03:00
Robert Mader
d3bdf92f09 backend-drm: Don't force non-opaque overlays to primary plane
If a view is non-opaque - such as an overlay over a video - we shouldn't
force it to be on the primary plane, as that's where the underlying
content should be placed, such as the video view.

dc0de9ee already mentioned: "This check should be changed in future to
only filter for opaque views, but that's for another time."

Adding "Fixes" at this is arguably a bug fix:
Fixes: dc0de9ee (backend-drm: Move overlay vs. primary plane check earlier)
Fixes: 2538aacc (backend-drm: Construct a zpos candidate list of planes)

Signed-off-by: Robert Mader <robert.mader@collabora.com>
(cherry picked from commit 5a2509ffb1)
2024-04-16 13:25:36 +03:00
Marius Vlad
02bc8571ee backend-pipewire: Move region initialization at the start
Failure to do so, might cause a crash if the output repaint happens
before the pipewire pipeline started -- calling pixman_region32_fini on
a uninitialized region.

Fixes 2abe4efcf7, "libweston/backends: Move damage flush into backends"

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
(cherry picked from commit b93335a741)
2024-04-16 13:25:36 +03:00
Derek Foreman
0126e6f275 libweston/backends: Move damage flush into backends
Currently we flush damage for the "primary plane" every repaint, but this
is folly.

The drm backend may skip rendering entirely if using an all-planes
composition. This could leave the renderer plane in a messy state if a
surface on an overlay plane disappears.

Instead, let the backends flush the primary plane damage when they know
they need to render.

Fixes #864

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
(cherry picked from commit 2abe4efcf7)
2024-04-16 13:25:35 +03:00
Derek Foreman
cebcf8ff7c libweston: Clip damage to paint node visible region
commit 79212ba9ad fixed a bug by
introducing a new one.

Before that point we could clip paint node damage to stale
visibility data. After that point we post damage for occluded
views, leading to large amounts of pointless drawing.

Add back the clip to visible region, in
weston_output_flush_damage_for_plane(), where we have up to date
visibility region information.

fixes 79212ba9ad

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
(cherry picked from commit e74f2897b9)
2024-04-16 13:25:35 +03:00
Ray Smith
17a9834892 backend-drm: fix confused fallback format handling
This seems to think formats needs to be NULL terminated, but it doesn't
and gl_renderer_get_egl_config asserts that all formats_count elements
are not NULL.

This happens when EGL_KHR_no_config_context is not supported.

Signed-off-by: Ray Smith <rsmith@brightsign.biz>
(cherry picked from commit 885c616589)
2024-04-16 13:25:35 +03:00
Michael Olbrich
f41ed41575 ivi-shell: clear seat focus if necessary when a surface is destroyed
Otherwise shseat->focused_ivisurf can point to deleted memory.
This does not happen with the hmi-controller because it explicitly assigns a new
focused surface. But the ivi-shell should not relay on the controller here.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
(cherry picked from commit d6681cedee)
2024-04-16 13:25:35 +03:00
Philipp Zabel
b0b004d891 libweston-desktop: Work around crash when opening popup menu
Fix a crash when right-clicking on a weston-terminal, where
weston_desktop_seat_popup_grab_add_surface() is called with
seat->popup_grab.keyboard.keyboard == NULL in case there is
no keyboard connected.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
(cherry picked from commit b72785e1f6)
2024-04-16 13:25:35 +03:00
Arnaud Vrac
54585a4cc9 clients/desktop-shell: fix crash on init when panel is disabled
The same output might be inited twice on init when the shell panel is disabled,
depending on the order the weston_desktop_shell and wl_output globals are
advertised. This triggers a protocol error as only one background can be created
per output.

Since initializing the output requires the weston_desktop_shell global (to
create the background and panel on this output), the output init call is done
conditionally in two places: in the global registry handler (to handle output
hotplug) and after the initial wl_display_roundtrip call to handle the case
where the weston_desktop_shell global was notified after the outputs.

We now check the output has already been initialized correctly by checking if
the background has been created, instead of the panel which is not always
created.

Signed-off-by: Arnaud Vrac <avrac@freebox.fr>
(cherry picked from commit 59207a7c7c)
2024-04-16 13:25:35 +03:00
Arnaud Vrac
5281e61fd3 desktop-shell: set proper curtain size when no output is created yet
In this case the curtain width and height would be calculated using
uninitialized values, triggering warnings in pixman calls.

Signed-off-by: Arnaud Vrac <avrac@freebox.fr>
(cherry picked from commit 03fa71f153)
2024-04-16 13:25:35 +03:00
Arnaud Vrac
52ef7ebbcc desktop-shell: clamp view alpha correctly
Clamping of the alpha value is not done properly since the introduction of the
weston_view_set_alpha() helper.

Signed-off-by: Arnaud Vrac <avrac@freebox.fr>
(cherry picked from commit 14e0fff19a)
2024-04-16 13:25:35 +03:00
Derek Foreman
d82762e6b7 gl-renderer: apply output transform before readback in repaint
When reading back for the remote backends we need to convert the extents
of the damage (which is in global coordinates) to output coordinates
to read back the correct region.

We were doing this in a bespoke fashion by adding the output coordinates.
Instead, use weston_matrix_transform_rect() to transform the extents by
the output transform - which includes the scale factor.

This fixes output scale on RDP with the gl renderer.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
(cherry picked from commit 527bc8aeb3)
2024-04-15 10:28:53 -05:00
Jeffy Chen
b49856fe53 renderer-gl: Fix wrong stride error when reading pixels
The gl_renderer_do_read_pixels() is expecting stride in bytes.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
(cherry picked from commit 623c7b5202)
2024-04-15 10:28:48 -05:00
24 changed files with 247 additions and 124 deletions

View File

@ -82,6 +82,7 @@ stages:
variables:
BUILD_OS: debian
LLVM_VERSION: 15
# If you upgrade from bookworm, see the use_tls=0 notes in tests/meson.build.
FDO_DISTRIBUTION_VERSION: bookworm
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'

View File

@ -4,3 +4,9 @@
# fontconfig library because turning off fast unwind -- required to catch other
# originating leaks from fontconfig; would stall our tests timing them out.
leak:libfontconfig
# Workarounds for the LeakSanitizer use_tls=0 workaround,
# see tests/meson.build
leak:wl_shm_buffer_begin_access
leak:g_malloc0
leak:/ld-*.so*

View File

@ -1586,7 +1586,7 @@ int main(int argc, char *argv[])
if (desktop.want_panel)
weston_desktop_shell_set_panel_position(desktop.shell, desktop.panel_position);
wl_list_for_each(output, &desktop.outputs, link)
if (!output->panel)
if (!output->background)
output_init(output, &desktop);
grab_surface_create(&desktop);

View File

@ -272,11 +272,10 @@ set_shsurf_size_maximized_or_fullscreen(struct shell_surface *shsurf,
width = shsurf->output->width;
height = shsurf->output->height;
}
}
/* take the panels into considerations */
if (max_requested)
} else if (max_requested) {
/* take the panels into considerations */
get_maximized_size(shsurf, &width, &height);
}
/* (0, 0) means we're back from one of the maximized/fullcreen states */
weston_desktop_surface_set_size(shsurf->desktop_surface, width, height);
@ -3351,10 +3350,7 @@ surface_opacity_binding(struct weston_pointer *pointer,
return;
alpha = shsurf->view->alpha - (event->value * step);
if (shsurf->view->alpha > 1.0)
shsurf->view->alpha = 1.0;
if (shsurf->view->alpha < step)
shsurf->view->alpha = step;
alpha = CLIP(alpha, step, 1.0);
weston_view_set_alpha(shsurf->view, alpha);
}
@ -3846,7 +3842,7 @@ shell_fade_create_view(struct desktop_shell *shell)
};
struct weston_curtain *curtain;
bool first = true;
int x1, y1, x2, y2;
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
wl_list_for_each(shell_output, &shell->output_list, link) {
struct weston_output *op = shell_output->output;

View File

@ -548,7 +548,7 @@ struct weston_output {
struct weston_log_pacer pixman_overdraw_pacer;
int (*start_repaint_loop)(struct weston_output *output);
int (*repaint)(struct weston_output *output, pixman_region32_t *damage);
int (*repaint)(struct weston_output *output);
void (*destroy)(struct weston_output *output);
void (*assign_planes)(struct weston_output *output);
int (*switch_mode)(struct weston_output *output, struct weston_mode *mode);

View File

@ -220,12 +220,19 @@ ivi_shell_surface_get_label(struct weston_surface *surface,
static void
layout_surface_cleanup(struct ivi_shell_surface *ivisurf)
{
struct weston_seat *seat;
assert(ivisurf->layout_surface != NULL);
/* destroy weston_surface destroy signal. */
if (!ivisurf->layout_surface->weston_desktop_surface)
wl_list_remove(&ivisurf->surface_destroy_listener.link);
wl_list_for_each(seat, &ivisurf->surface->compositor->seat_list, link) {
struct ivi_shell_seat *shseat = get_ivi_shell_seat(seat);
if (shseat->focused_ivisurf == ivisurf->layout_surface)
shseat->focused_ivisurf = NULL;
}
ivi_layout_surface_destroy(ivisurf->layout_surface);
ivisurf->layout_surface = NULL;

View File

@ -82,18 +82,17 @@ drm_backend_create_gl_renderer(struct drm_backend *b)
const struct pixel_format_info *format[3] = {
b->format,
fallback_format_for(b->format),
NULL,
};
struct gl_renderer_display_options options = {
.egl_platform = EGL_PLATFORM_GBM_KHR,
.egl_native_display = b->gbm,
.egl_surface_type = EGL_WINDOW_BIT,
.formats = format,
.formats_count = 2,
.formats_count = 1,
};
if (format[1])
options.formats_count = 3;
options.formats_count = 2;
return weston_compositor_init_renderer(b->compositor,
WESTON_RENDERER_GL,

View File

@ -965,7 +965,7 @@ bool
drm_plane_is_available(struct drm_plane *plane, struct drm_output *output);
void
drm_output_render(struct drm_output_state *state, pixman_region32_t *damage);
drm_output_render(struct drm_output_state *state);
int
parse_gbm_format(const char *s, const struct pixel_format_info *default_format,

View File

@ -202,8 +202,7 @@ drm_virtual_output_submit_frame(struct drm_output *output,
}
static int
drm_virtual_output_repaint(struct weston_output *output_base,
pixman_region32_t *damage)
drm_virtual_output_repaint(struct weston_output *output_base)
{
struct drm_output_state *state = NULL;
struct drm_output *output = to_drm_output(output_base);
@ -237,7 +236,7 @@ drm_virtual_output_repaint(struct weston_output *output_base,
pending_state,
DRM_OUTPUT_STATE_CLEAR_PLANES);
drm_output_render(state, damage);
drm_output_render(state);
scanout_state = drm_output_state_get_plane(state, scanout_plane);
if (!scanout_state || !scanout_state->fb)
goto err;

View File

@ -75,56 +75,78 @@ static void
drm_backend_create_faked_zpos(struct drm_device *device)
{
struct drm_backend *b = device->backend;
struct drm_plane *plane;
struct drm_plane *plane, *tmp;
struct wl_list tmp_list;
uint64_t zpos = 0ULL;
uint64_t zpos_min_primary;
uint64_t zpos_min_overlay;
uint64_t zpos_min_cursor;
zpos_min_primary = zpos;
/* if the property is there, bail out sooner */
wl_list_for_each(plane, &device->plane_list, link) {
/* if the property is there, bail out sooner */
if (plane->props[WDRM_PLANE_ZPOS].prop_id != 0)
return;
if (plane->type != WDRM_PLANE_TYPE_PRIMARY)
continue;
zpos++;
}
zpos_min_overlay = zpos;
wl_list_for_each(plane, &device->plane_list, link) {
if (plane->type != WDRM_PLANE_TYPE_OVERLAY)
continue;
zpos++;
}
zpos_min_cursor = zpos;
wl_list_for_each(plane, &device->plane_list, link) {
if (plane->type != WDRM_PLANE_TYPE_CURSOR)
continue;
zpos++;
}
drm_debug(b, "[drm-backend] zpos property not found. "
"Using invented immutable zpos values:\n");
/* assume that invented zpos values are immutable */
wl_list_for_each(plane, &device->plane_list, link) {
if (plane->type == WDRM_PLANE_TYPE_PRIMARY) {
plane->zpos_min = zpos_min_primary;
plane->zpos_max = zpos_min_primary;
} else if (plane->type == WDRM_PLANE_TYPE_OVERLAY) {
plane->zpos_min = zpos_min_overlay;
plane->zpos_max = zpos_min_overlay;
} else if (plane->type == WDRM_PLANE_TYPE_CURSOR) {
plane->zpos_min = zpos_min_cursor;
plane->zpos_max = zpos_min_cursor;
}
wl_list_init(&tmp_list);
wl_list_insert_list(&tmp_list, &device->plane_list);
wl_list_init(&device->plane_list);
zpos_min_primary = zpos;
wl_list_for_each_safe(plane, tmp, &tmp_list, link) {
if (plane->type != WDRM_PLANE_TYPE_PRIMARY)
continue;
plane->zpos_min = zpos_min_primary;
plane->zpos_max = zpos_min_primary;
wl_list_remove(&plane->link);
wl_list_insert(&device->plane_list, &plane->link);
zpos++;
drm_debug(b, "\t[plane] %s plane %d, zpos_min %"PRIu64", "
"zpos_max %"PRIu64"\n",
drm_output_get_plane_type_name(plane),
plane->plane_id, plane->zpos_min, plane->zpos_max);
}
zpos_min_overlay = zpos;
wl_list_for_each_safe(plane, tmp, &tmp_list, link) {
if (plane->type != WDRM_PLANE_TYPE_OVERLAY)
continue;
plane->zpos_min = zpos_min_overlay;
plane->zpos_max = zpos_min_overlay;
wl_list_remove(&plane->link);
wl_list_insert(&device->plane_list, &plane->link);
zpos++;
drm_debug(b, "\t[plane] %s plane %d, zpos_min %"PRIu64", "
"zpos_max %"PRIu64"\n",
drm_output_get_plane_type_name(plane),
plane->plane_id, plane->zpos_min, plane->zpos_max);
}
zpos_min_cursor = zpos;
wl_list_for_each_safe(plane, tmp, &tmp_list, link) {
if (plane->type != WDRM_PLANE_TYPE_CURSOR)
continue;
plane->zpos_min = zpos_min_cursor;
plane->zpos_max = zpos_min_cursor;
wl_list_remove(&plane->link);
wl_list_insert(&device->plane_list, &plane->link);
zpos++;
drm_debug(b, "\t[plane] %s plane %d, zpos_min %"PRIu64", "
"zpos_max %"PRIu64"\n",
drm_output_get_plane_type_name(plane),
plane->plane_id, plane->zpos_min, plane->zpos_max);
}
assert(wl_list_empty(&tmp_list));
}
static int
@ -355,7 +377,7 @@ drm_output_render_pixman(struct drm_output_state *state,
}
void
drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
drm_output_render(struct drm_output_state *state)
{
struct drm_output *output = state->output;
struct drm_device *device = output->device;
@ -365,7 +387,7 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
struct drm_property_info *damage_info =
&scanout_plane->props[WDRM_PLANE_FB_DAMAGE_CLIPS];
struct drm_fb *fb;
pixman_region32_t scanout_damage;
pixman_region32_t damage, scanout_damage;
pixman_box32_t *rects;
int n_rects;
@ -375,6 +397,10 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
if (scanout_state->fb)
return;
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(&output->base, &damage);
/*
* If we don't have any damage on the primary plane, and we already
* have a renderer buffer active, we can reuse it; else we pass
@ -382,7 +408,7 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
* area. But, we still have to call the renderer anyway if any screen
* capture is pending, otherwise the capture will not complete.
*/
if (!pixman_region32_not_empty(damage) &&
if (!pixman_region32_not_empty(&damage) &&
wl_list_empty(&output->base.frame_signal.listener_list) &&
!weston_output_has_renderer_capture_tasks(&output->base) &&
scanout_plane->state_cur->fb &&
@ -390,14 +416,14 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB)) {
fb = drm_fb_ref(scanout_plane->state_cur->fb);
} else if (c->renderer->type == WESTON_RENDERER_PIXMAN) {
fb = drm_output_render_pixman(state, damage);
fb = drm_output_render_pixman(state, &damage);
} else {
fb = drm_output_render_gl(state, damage);
fb = drm_output_render_gl(state, &damage);
}
if (!fb) {
drm_plane_state_put_back(scanout_state);
return;
goto out;
}
scanout_state->fb = fb;
@ -417,13 +443,13 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
/* Don't bother calculating plane damage if the plane doesn't support it */
if (damage_info->prop_id == 0)
return;
goto out;
pixman_region32_init(&scanout_damage);
weston_region_global_to_output(&scanout_damage,
&output->base,
damage);
&damage);
assert(scanout_state->damage_blob_id == 0);
@ -440,6 +466,8 @@ drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
&scanout_state->damage_blob_id);
pixman_region32_fini(&scanout_damage);
out:
pixman_region32_fini(&damage);
}
static uint32_t
@ -651,7 +679,7 @@ cursor_bo_update(struct drm_output *output, struct weston_view *ev)
#endif
static int
drm_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
drm_output_repaint(struct weston_output *output_base)
{
struct drm_output *output = to_drm_output(output_base);
struct drm_output_state *state = NULL;
@ -718,7 +746,7 @@ drm_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
if (device->atomic_modeset)
drm_output_pick_writeback_capture_task(output);
drm_output_render(state, damage);
drm_output_render(state);
scanout_state = drm_output_state_get_plane(state,
output->scanout_plane);
if (!scanout_state || !scanout_state->fb)

View File

@ -508,6 +508,7 @@ drm_output_find_plane_for_view(struct drm_output_state *state,
/* if the view covers the whole output, put it in the
* scanout plane, not overlay */
if (view_matches_entire_output &&
weston_view_is_opaque(ev, &ev->transform.boundingbox) &&
!scanout_has_view_assigned)
continue;
break;

View File

@ -152,11 +152,11 @@ headless_output_update_gl_border(struct headless_output *output)
}
static int
headless_output_repaint(struct weston_output *output_base,
pixman_region32_t *damage)
headless_output_repaint(struct weston_output *output_base)
{
struct headless_output *output = to_headless_output(output_base);
struct weston_compositor *ec;
pixman_region32_t damage;
assert(output);
@ -164,9 +164,15 @@ headless_output_repaint(struct weston_output *output_base,
headless_output_update_gl_border(output);
ec->renderer->repaint_output(&output->base, damage,
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
ec->renderer->repaint_output(&output->base, &damage,
output->renderbuffer);
pixman_region32_fini(&damage);
wl_event_source_timer_update(output->finish_frame_timer, 16);
return 0;

View File

@ -725,19 +725,24 @@ pipewire_submit_buffer(struct pipewire_output *output,
}
static int
pipewire_output_repaint(struct weston_output *base, pixman_region32_t *damage)
pipewire_output_repaint(struct weston_output *base)
{
struct pipewire_output *output = to_pipewire_output(base);
struct weston_compositor *ec = output->base.compositor;
struct pw_buffer *buffer;
struct pipewire_frame_data *frame_data;
pixman_region32_t damage;
assert(output);
pixman_region32_init(&damage);
if (pw_stream_get_state(output->stream, NULL) != PW_STREAM_STATE_STREAMING)
goto out;
if (!pixman_region32_not_empty(damage))
weston_output_flush_damage_for_primary_plane(base, &damage);
if (!pixman_region32_not_empty(&damage))
goto out;
buffer = pw_stream_dequeue_buffer(output->stream);
@ -748,12 +753,14 @@ pipewire_output_repaint(struct weston_output *base, pixman_region32_t *damage)
pipewire_output_debug(output, "dequeued buffer: %p", buffer);
frame_data = buffer->user_data;
ec->renderer->repaint_output(&output->base, damage, frame_data->renderbuffer);
ec->renderer->repaint_output(&output->base, &damage, frame_data->renderbuffer);
pipewire_submit_buffer(output, buffer);
out:
pixman_region32_fini(&damage);
weston_output_arm_frame_timer(base, output->finish_frame_timer);
return 0;

View File

@ -272,24 +272,29 @@ rdp_output_start_repaint_loop(struct weston_output *output)
}
static int
rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
rdp_output_repaint(struct weston_output *output_base)
{
struct rdp_output *output = container_of(output_base, struct rdp_output, base);
struct weston_compositor *ec = output->base.compositor;
struct rdp_backend *b = output->backend;
struct rdp_peers_item *peer;
pixman_region32_t damage;
assert(output);
ec->renderer->repaint_output(&output->base, damage,
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
ec->renderer->repaint_output(&output->base, &damage,
output->renderbuffer);
if (pixman_region32_not_empty(damage)) {
if (pixman_region32_not_empty(&damage)) {
pixman_region32_t transformed_damage;
pixman_region32_init(&transformed_damage);
weston_region_global_to_output(&transformed_damage,
output_base,
damage);
&damage);
wl_list_for_each(peer, &b->peers, link) {
if ((peer->flags & RDP_PEER_ACTIVATED) &&
(peer->flags & RDP_PEER_OUTPUT_ENABLED)) {
@ -299,6 +304,8 @@ rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
pixman_region32_fini(&transformed_damage);
}
pixman_region32_fini(&damage);
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
return 0;

View File

@ -1004,10 +1004,11 @@ vnc_output_start_repaint_loop(struct weston_output *output)
}
static int
vnc_output_repaint(struct weston_output *base, pixman_region32_t *damage)
vnc_output_repaint(struct weston_output *base)
{
struct vnc_output *output = to_vnc_output(base);
struct vnc_backend *backend = output->backend;
pixman_region32_t damage;
assert(output);
@ -1016,10 +1017,16 @@ vnc_output_repaint(struct weston_output *base, pixman_region32_t *damage)
vnc_output_update_cursor(output);
if (pixman_region32_not_empty(damage)) {
vnc_update_buffer(output->display, damage);
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(base, &damage);
if (pixman_region32_not_empty(&damage)) {
vnc_update_buffer(output->display, &damage);
}
pixman_region32_fini(&damage);
/*
* Make sure damage of this (or previous) damage is handled
*

View File

@ -498,22 +498,28 @@ wayland_output_start_repaint_loop(struct weston_output *output_base)
#ifdef ENABLE_EGL
static int
wayland_output_repaint_gl(struct weston_output *output_base,
pixman_region32_t *damage)
wayland_output_repaint_gl(struct weston_output *output_base)
{
struct wayland_output *output = to_wayland_output(output_base);
struct weston_compositor *ec;
pixman_region32_t damage;
assert(output);
ec = output->base.compositor;
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
output->frame_cb = wl_surface_frame(output->parent.surface);
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
wayland_output_update_gl_border(output);
ec->renderer->repaint_output(&output->base, damage, NULL);
ec->renderer->repaint_output(&output->base, &damage, NULL);
pixman_region32_fini(&damage);
return 0;
}
@ -604,17 +610,21 @@ wayland_shm_buffer_attach(struct wayland_shm_buffer *sb,
}
static int
wayland_output_repaint_pixman(struct weston_output *output_base,
pixman_region32_t *damage)
wayland_output_repaint_pixman(struct weston_output *output_base)
{
struct wayland_output *output = to_wayland_output(output_base);
struct wayland_backend *b;
struct wayland_shm_buffer *sb;
pixman_region32_t damage;
assert(output);
b = output->backend;
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
if (output->frame) {
if (frame_status(output->frame) & FRAME_STATUS_REPAINT)
wl_list_for_each(sb, &output->shm.buffers, link)
@ -624,10 +634,12 @@ wayland_output_repaint_pixman(struct weston_output *output_base,
sb = wayland_output_get_shm_buffer(output);
wayland_output_update_shm_border(sb);
b->compositor->renderer->repaint_output(output_base, damage,
b->compositor->renderer->repaint_output(output_base, &damage,
sb->renderbuffer);
wayland_shm_buffer_attach(sb, damage);
wayland_shm_buffer_attach(sb, &damage);
pixman_region32_fini(&damage);
output->frame_cb = wl_surface_frame(output->parent.surface);
wl_callback_add_listener(output->frame_cb, &frame_listener, output);

View File

@ -429,17 +429,23 @@ x11_output_start_repaint_loop(struct weston_output *output)
}
static int
x11_output_repaint_gl(struct weston_output *output_base,
pixman_region32_t *damage)
x11_output_repaint_gl(struct weston_output *output_base)
{
struct x11_output *output = to_x11_output(output_base);
struct weston_compositor *ec;
pixman_region32_t damage;
assert(output);
ec = output->base.compositor;
ec->renderer->repaint_output(output_base, damage, NULL);
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
ec->renderer->repaint_output(output_base, &damage, NULL);
pixman_region32_fini(&damage);
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
return 0;
@ -498,8 +504,7 @@ set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region
static int
x11_output_repaint_shm(struct weston_output *output_base,
pixman_region32_t *damage)
x11_output_repaint_shm(struct weston_output *output_base)
{
struct x11_output *output = to_x11_output(output_base);
const struct weston_renderer *renderer;
@ -508,6 +513,7 @@ x11_output_repaint_shm(struct weston_output *output_base,
struct x11_backend *b;
xcb_void_cookie_t cookie;
xcb_generic_error_t *err;
pixman_region32_t damage;
assert(output);
@ -517,9 +523,16 @@ x11_output_repaint_shm(struct weston_output *output_base,
image = renderer->pixman->renderbuffer_get_image(output->renderbuffer);
ec->renderer->repaint_output(output_base, damage, output->renderbuffer);
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
ec->renderer->repaint_output(output_base, &damage, output->renderbuffer);
set_clip_for_output(output_base, &damage);
pixman_region32_fini(&damage);
set_clip_for_output(output_base, damage);
cookie = xcb_shm_put_image_checked(b->conn, output->window, output->gc,
pixman_image_get_width(image),
pixman_image_get_height(image),

View File

@ -327,4 +327,8 @@ weston_output_flush_damage_for_plane(struct weston_output *output,
struct weston_plane *plane,
pixman_region32_t *damage);
void
weston_output_flush_damage_for_primary_plane(struct weston_output *output,
pixman_region32_t *damage);
#endif

View File

@ -3378,6 +3378,12 @@ weston_output_flush_damage_for_plane(struct weston_output *output,
continue;
changed = true;
/* We can safely clip paint node damage to visible region
* here, as we're only dealing with nodes on this output,
* and the visibility regions for paint nodes on this
* output are up to date.
*/
pixman_region32_intersect(&pnode->damage, &pnode->damage, &pnode->visible);
pixman_region32_union(damage, damage, &pnode->damage);
pixman_region32_clear(&pnode->damage);
}
@ -3385,6 +3391,20 @@ weston_output_flush_damage_for_plane(struct weston_output *output,
return changed;
}
WL_EXPORT void
weston_output_flush_damage_for_primary_plane(struct weston_output *output,
pixman_region32_t *damage)
{
weston_output_flush_damage_for_plane(output,
&output->primary_plane,
damage);
if (output->full_repaint_needed) {
pixman_region32_copy(damage, &output->region);
output->full_repaint_needed = false;
}
}
static int
weston_output_repaint(struct weston_output *output)
{
@ -3393,7 +3413,6 @@ weston_output_repaint(struct weston_output *output)
struct weston_animation *animation, *next;
struct wl_resource *cb, *cnext;
struct wl_list frame_callback_list;
pixman_region32_t output_damage;
int r;
uint32_t frame_time_msec;
enum weston_hdcp_protection highest_requested = WESTON_HDCP_DISABLE;
@ -3465,19 +3484,7 @@ weston_output_repaint(struct weston_output *output)
output_accumulate_damage(output);
pixman_region32_init(&output_damage);
weston_output_flush_damage_for_plane(output, &output->primary_plane,
&output_damage);
if (output->full_repaint_needed) {
pixman_region32_copy(&output_damage, &output->region);
output->full_repaint_needed = false;
}
r = output->repaint(output, &output_damage);
pixman_region32_fini(&output_damage);
r = output->repaint(output);
output->repaint_needed = false;
if (r == 0)
@ -3844,17 +3851,10 @@ weston_view_move_to_layer(struct weston_view *view,
struct weston_layer_entry *layer)
{
bool was_mapped = view->is_mapped;
struct weston_paint_node *pnode, *pntmp;
if (layer == &view->layer_link)
return;
/* Remove all paint nodes because we have no idea what a layer change
* does to view visibility on any output.
*/
wl_list_for_each_safe(pnode, pntmp, &view->paint_node_list, view_link)
weston_paint_node_destroy(pnode);
view->surface->compositor->view_list_needs_rebuild = true;
/* Damage the view's old region, and remove it from the layer. */
@ -3884,6 +3884,18 @@ weston_view_move_to_layer(struct weston_view *view,
WL_EXPORT void
weston_layer_entry_remove(struct weston_layer_entry *entry)
{
struct weston_paint_node *pnode, *pntmp;
struct weston_view *view;
/* Remove all paint nodes because we have no idea what a layer change
* does to view visibility on any output.
*/
view = container_of(entry, struct weston_view, layer_link);
view->surface->compositor->view_list_needs_rebuild = true;
wl_list_for_each_safe(pnode, pntmp, &view->paint_node_list, view_link)
weston_paint_node_destroy(pnode);
wl_list_remove(&entry->link);
wl_list_init(&entry->link);
entry->layer = NULL;

View File

@ -532,6 +532,9 @@ weston_desktop_seat_popup_grab_add_surface(struct weston_desktop_seat *seat,
wl_list_insert(&seat->popup_grab.surfaces, link);
if (!seat->popup_grab.keyboard.keyboard)
return;
desktop_surface =
weston_desktop_seat_popup_grab_get_topmost_surface(seat);
surface = weston_desktop_surface_get_surface(desktop_surface);
@ -552,6 +555,9 @@ weston_desktop_seat_popup_grab_remove_surface(struct weston_desktop_seat *seat,
struct weston_desktop_surface *desktop_surface;
struct weston_surface *surface;
if (!seat->popup_grab.keyboard.keyboard)
return;
desktop_surface =
weston_desktop_seat_popup_grab_get_topmost_surface(seat);
surface = weston_desktop_surface_get_surface(desktop_surface);

View File

@ -892,6 +892,8 @@ weston_desktop_surface_foreach_child(struct weston_desktop_surface *surface,
{
struct weston_desktop_surface *child;
wl_list_for_each(child, &surface->children_list, children_link)
callback(child, user_data);
wl_list_for_each(child, &surface->children_list, children_link) {
if (weston_desktop_surface_get_user_data(child))
callback(child, user_data);
}
}

View File

@ -2021,30 +2021,35 @@ gl_renderer_repaint_output(struct weston_output *output,
if (rb->pixels) {
uint32_t *pixels = rb->pixels;
int stride = go->fb_size.width;
pixman_box32_t *extents = &rb->base.damage.extents;
int width = go->fb_size.width;
int stride = width * (compositor->read_format->bpp >> 3);
pixman_box32_t extents;
struct weston_geometry rect = {
.x = go->area.x,
.width = go->area.width,
};
extents = weston_matrix_transform_rect(&output->matrix,
rb->base.damage.extents);
if (gr->fan_debug) {
rect.y = go->fb_size.height - go->area.y - go->area.height;
rect.height = go->area.height;
} else {
rect.y = go->fb_size.height - go->area.y - extents->y2;
rect.height = extents->y2 - extents->y1;
pixels += rect.width * (extents->y1 - (int)output->pos.c.y);
rect.y = go->fb_size.height - go->area.y - extents.y2;
rect.height = extents.y2 - extents.y1;
pixels += rect.width * extents.y1;
}
if (gr->gl_version >= gr_gl_version(3, 0) && ! gr->fan_debug) {
glPixelStorei(GL_PACK_ROW_LENGTH, stride);
rect.width = extents->x2 - extents->x1;
rect.x += extents->x1 - (int)output->pos.c.x;
pixels += extents->x1 - (int)output->pos.c.x;
glPixelStorei(GL_PACK_ROW_LENGTH, width);
rect.width = extents.x2 - extents.x1;
rect.x += extents.x1;
pixels += extents.x1;
}
gl_renderer_do_read_pixels(gr, compositor->read_format, pixels, stride, &rect);
gl_renderer_do_read_pixels(gr, compositor->read_format, pixels,
stride, &rect);
if (gr->gl_version >= gr_gl_version(3, 0))
glPixelStorei(GL_PACK_ROW_LENGTH, 0);

View File

@ -1,6 +1,6 @@
project('weston',
'c',
version: '13.0.0',
version: '13.0.3',
default_options: [
'warning_level=3',
'c_std=gnu99',

View File

@ -420,9 +420,14 @@ configure_file(output: 'test-config.h', configuration: test_config_h)
test_env = {}
# there are some leaks in fontconfig we can't fix;
# there are some leaks in fontconfig we can't fix;
# use_tls=0 is a workaround for LeakSanitizer crashing after successful
# program exit when it scans for leaks. Due to use_tls=0 even more
# suppressions had to be added.
# TODO XXX: Try to revert the addition of use_tls=0 when our CI image
# upgrades from Debian Bookworm to something more recent.
if get_option('b_sanitize') in ['address', 'address,undefined' ]
test_env += { 'LSAN_OPTIONS': 'suppressions=@0@'.format(dir_gitlab_ci / 'leak-sanitizer.supp') }
test_env += { 'LSAN_OPTIONS': 'use_tls=0:suppressions=@0@'.format(dir_gitlab_ci / 'leak-sanitizer.supp') }
endif
foreach t : tests