Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package weston for openSUSE:Factory checked in at 2022-08-10 17:14:32 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/weston (Old) and /work/SRC/openSUSE:Factory/.weston.new.1521 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "weston" Wed Aug 10 17:14:32 2022 rev:27 rq:994204 version:10.0.2 Changes: -------- --- /work/SRC/openSUSE:Factory/weston/weston.changes 2022-02-02 22:45:01.942060204 +0100 +++ /work/SRC/openSUSE:Factory/.weston.new.1521/weston.changes 2022-08-10 17:15:41.898083585 +0200 @@ -1,0 +2,34 @@ +Tue Aug 9 20:21:35 UTC 2022 - Dirk M??ller <[email protected]> + +- update to 10.0.2: + This is a bugfix release for 10.0.0. + * clients/simple-dmabuf-feedback: do not use buffer before compositor's response + * kiosk-shell: Check if app_ids have been set after initial commit + * kiosk-shell: Don't occlude shsurf on other outputs + * kiosk-shell: Favor out views on same output + * libweston: Assert if ref-count balance is wrong + * libweston, desktop-shell: Add a wrapper for weston_surface reference + * desktop-shell: Create a distinct view for the fade-out close anim + * desktop-shell: Rename destroy_layer functions + * desktop-shell: Migrate surface_unlink_view + * desktop-shell: Check for a valid desktop_surface + * desktop-shell: Clarify weston_view destruction at tear down + * desktop-shell: Add missing weston_view_destroy() + * simple-egl: Add start as maximized + * libweston-desktop: Replace buffer with geometry + * simple-egl: Remove uneeded check + * simple-egl: Defer EGL surface/window creation + * simple-egl: Move set_fullscreen/set_maximized before initial commit + * gl-renderer: fix performance regression in frag + * libweston/compositor: Cache buffer damage for synced subsurfaces + * tests: Add test for synced subsurfaces and buffer damage + * libweston/compositor: Do not map subsurfaces without buffer + * tests: Add test for subsurfaces mapping hierachies + * clients/simple-dmabuf-feedback: Support multi-tranche feedbacks + * clients/simple-dmabuf-*: Increase buffer limit to four + * clients/simple-dmabuf-feedback: Add fallback print method for unknown formats + * backend-drm: Add failure reasons for failing gbm_bo_import + * clients/simple-dmabuf-feedback: use time instead of redraws + * libweston/linux-dmabuf: create surface feedback on demand + +------------------------------------------------------------------- Old: ---- weston-10.0.0.tar.xz weston-10.0.0.tar.xz.sig New: ---- weston-10.0.2.tar.xz weston-10.0.2.tar.xz.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ weston.spec ++++++ --- /var/tmp/diff_new_pack.5xoVj8/_old 2022-08-10 17:15:42.614085454 +0200 +++ /var/tmp/diff_new_pack.5xoVj8/_new 2022-08-10 17:15:42.622085475 +0200 @@ -19,18 +19,17 @@ Name: weston %define lname libweston0 %define major 10 -%define realver 10.0.0 -Version: 10 +%define realver 10.0.2 +Version: 10.0.2 Release: 0 Summary: Wayland Reference Compositor License: CC-BY-SA-3.0 AND MIT Group: System/X11/Servers URL: https://wayland.freedesktop.org/ - #Git-Clone: git://anongit.freedesktop.org/wayland/weston #Git-Web: https://cgit.freedesktop.org/wayland/weston/ -Source: https://wayland.freedesktop.org/releases/weston-%realver.tar.xz -Source2: https://wayland.freedesktop.org/releases/weston-%realver.tar.xz.sig +Source: https://gitlab.freedesktop.org/wayland/weston/-/releases/%realver/downloads/weston-%realver.tar.xz +Source2: https://gitlab.freedesktop.org/wayland/weston/-/releases/%realver/downloads/weston-%realver.tar.xz.sig Source3: %name.keyring BuildRequires: Mesa-libGLESv3-devel BuildRequires: autoconf >= 2.64 ++++++ weston-10.0.0.tar.xz -> weston-10.0.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/.gitlab-ci.yml new/weston-10.0.2/.gitlab-ci.yml --- old/weston-10.0.0/.gitlab-ci.yml 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/.gitlab-ci.yml 2022-07-26 12:22:25.000000000 +0200 @@ -296,7 +296,9 @@ - .build-options-full artifacts: reports: - cobertura: $BUILDDIR/meson-logs/coverage.xml + coverage_report: + coverage_format: cobertura + path: $BUILDDIR/meson-logs/coverage.xml aarch64-debian-full-build: extends: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/clients/simple-dmabuf-egl.c new/weston-10.0.2/clients/simple-dmabuf-egl.c --- old/weston-10.0.0/clients/simple-dmabuf-egl.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/clients/simple-dmabuf-egl.c 2022-07-26 12:22:25.000000000 +0200 @@ -131,7 +131,7 @@ int release_fence_fd; }; -#define NUM_BUFFERS 3 +#define NUM_BUFFERS 4 struct window { struct display *display; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/clients/simple-dmabuf-feedback.c new/weston-10.0.2/clients/simple-dmabuf-feedback.c --- old/weston-10.0.0/clients/simple-dmabuf-feedback.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/clients/simple-dmabuf-feedback.c 2022-07-26 12:22:25.000000000 +0200 @@ -26,11 +26,13 @@ #include "config.h" #include <assert.h> +#include <ctype.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <libudev.h> #include <sys/mman.h> +#include <time.h> #include "shared/helpers.h" #include "shared/platform.h" @@ -47,7 +49,7 @@ #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> -#define NUM_BUFFERS 3 +#define NUM_BUFFERS 4 /* We have to hack the DRM-backend to pretend that planes of the underlying * hardware don't support this format. If you change the value of this constant, @@ -140,7 +142,11 @@ struct buffer { struct window *window; struct wl_buffer *buffer; - bool busy; + enum { + NOT_CREATED, + IN_USE, + AVAILABLE + } status; bool recreate; int dmabuf_fds[4]; struct gbm_bo *bo; @@ -469,7 +475,7 @@ { struct buffer *buf = data; - buf->busy = false; + buf->status = AVAILABLE; if (buf->recreate) buffer_recreate(buf); @@ -485,6 +491,7 @@ { struct buffer *buf = data; + buf->status = AVAILABLE; buf->buffer = new_buffer; wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); zwp_linux_buffer_params_v1_destroy(params); @@ -516,6 +523,7 @@ struct zwp_linux_buffer_params_v1 *params; int i; + buf->status = NOT_CREATED; buf->window = window; buf->width = width; buf->height = height; @@ -573,8 +581,22 @@ unsigned int i; for (i = 0; i < NUM_BUFFERS; i++) - if (!window->buffers[i].busy) + if (window->buffers[i].status == AVAILABLE) return &window->buffers[i]; + + /* In this client, we sometimes have to recreate the buffers. As we are + * not using the create_immed request from zwp_linux_dmabuf_v1, we need + * to wait an event from the server (what leads to create_succeeded() + * being called in this client). So if all buffers are busy, it may be + * the case in which all the buffers were recreated but the server still + * didn't send the events. This is very unlikely to happen, but a + * roundtrip() guarantees that we receive and process the events. */ + wl_display_roundtrip(window->display->display); + + for (i = 0; i < NUM_BUFFERS; i++) + if (window->buffers[i].status == AVAILABLE) + return &window->buffers[i]; + return NULL; } @@ -639,15 +661,13 @@ window->callback = wl_surface_frame(window->surface); wl_callback_add_listener(window->callback, &frame_listener, window); wl_surface_commit(window->surface); - buf->busy = true; + buf->status = IN_USE; region = wl_compositor_create_region(window->display->compositor); wl_region_add(region, 0, 0, window->display->output.width, window->display->output.height); wl_surface_set_opaque_region(window->surface, region); wl_region_destroy(region); - - window->n_redraws++; } static const struct wl_callback_listener frame_listener = { @@ -1050,18 +1070,54 @@ } } +static char +bits2graph(uint32_t value, unsigned bitoffset) +{ + int c = (value >> bitoffset) & 0xff; + + if (isgraph(c) || isspace(c)) + return c; + + return '?'; +} + +static void +fourcc2str(uint32_t format, char *str, int len) +{ + int i; + + assert(len >= 5); + + for (i = 0; i < 4; i++) + str[i] = bits2graph(format, i * 8); + str[i] = '\0'; +} + static void print_tranche_format_modifier(uint32_t format, uint64_t modifier) { const struct pixel_format_info *fmt_info; + char *format_str; char *mod_name; + int len; - fmt_info = pixel_format_get_info(format); mod_name = pixel_format_get_modifier(modifier); + fmt_info = pixel_format_get_info(format); + + if (fmt_info) { + len = asprintf(&format_str, "%s", fmt_info->drm_format_name); + } else { + char fourcc_str[5]; + + fourcc2str(format, fourcc_str, sizeof(fourcc_str)); + len = asprintf(&format_str, "0x%08x (%s)", format, fourcc_str); + } + assert(len > 0); fprintf(stderr, "??? ???????????????????????????tranche format/modifier pair - format %s, modifier %s\n", - fmt_info ? fmt_info->drm_format_name : "UNKNOWN", mod_name); + format_str, mod_name); + free(format_str); free(mod_name); } @@ -1103,7 +1159,7 @@ dmabuf_feedback_tranche_init(&feedback->pending_tranche); } -static void +static bool pick_initial_format_from_renderer_tranche(struct window *window, struct dmabuf_feedback_tranche *tranche) { @@ -1117,13 +1173,12 @@ window->format.format = fmt->format; wl_array_copy(&window->format.modifiers, &fmt->modifiers); - return; + return true; } - - assert(0 && "error: INITIAL_BUFFER_FORMAT not supported by the hardware"); + return false; } -static void +static bool pick_format_from_scanout_tranche(struct window *window, struct dmabuf_feedback_tranche *tranche) { @@ -1132,8 +1187,9 @@ wl_array_for_each(fmt, &tranche->formats.arr) { - /* Ignore format that we're already using. */ - if (fmt->format == window->format.format) + /* Ignore the format that we want to pick from the render + * tranche. */ + if (fmt->format == INITIAL_BUFFER_FORMAT) continue; /* Format should be supported by the compositor. */ @@ -1147,10 +1203,9 @@ window->format.format = fmt->format; wl_array_copy(&window->format.modifiers, &fmt->modifiers); - return; + return true; } - - assert(0 && "error: no valid pair of format/modifier in the scanout tranche"); + return false; } static void @@ -1158,25 +1213,37 @@ { struct window *window = data; struct dmabuf_feedback_tranche *tranche; + bool got_scanout_tranche = false; unsigned int i; fprintf(stderr, "???end of dma-buf feedback\n\n"); /* The first time that we receive dma-buf feedback for a surface it - * contains only the renderer tranche. We pick the INITIAL_BUFFER_FORMAT + * contains only the renderer tranches. We pick the INITIAL_BUFFER_FORMAT * from there. Then the compositor should detect that the format is * unsupported by the underlying hardware (not actually, but you should - * have faked this in the DRM-backend) and send the scanout tranche. We - * use the formats/modifiers of the scanout tranche to reallocate our + * have faked this in the DRM-backend) and send the scanout tranches. We + * use the formats/modifiers of the scanout tranches to reallocate our * buffers. */ wl_array_for_each(tranche, &window->pending_dmabuf_feedback.tranches) { if (tranche->is_scanout_tranche) { - pick_format_from_scanout_tranche(window, tranche); - for (i = 0; i < NUM_BUFFERS; i++) - window->buffers[i].recreate = true; - break; + got_scanout_tranche = true; + if (pick_format_from_scanout_tranche(window, tranche)) { + for (i = 0; i < NUM_BUFFERS; i++) + window->buffers[i].recreate = true; + break; + } } - pick_initial_format_from_renderer_tranche(window, tranche); + if (pick_initial_format_from_renderer_tranche(window, tranche)) + break; + } + + if (got_scanout_tranche) { + assert(window->format.format != INITIAL_BUFFER_FORMAT && + "error: no valid pair of format/modifier in the scanout tranches"); + } else { + assert(window->format.format == INITIAL_BUFFER_FORMAT && + "error: INITIAL_BUFFER_FORMAT not supported by the hardware"); } dmabuf_feedback_fini(&window->dmabuf_feedback); @@ -1383,6 +1450,9 @@ struct display *display; struct window *window; int ret = 0; + struct timespec start_time, current_time; + const time_t MAX_TIME_SECONDS = 3; + time_t delta_time = 0; fprintf(stderr, "This client was written with the purpose of manually test " \ "Weston's dma-buf feedback implementation. See main() " \ @@ -1391,9 +1461,14 @@ display = create_display(); window = create_window(display); + clock_gettime(CLOCK_MONOTONIC, &start_time); + redraw(window, NULL, 0); - while (ret != -1 && window->n_redraws < 200) + while (ret != -1 && delta_time < MAX_TIME_SECONDS) { ret = wl_display_dispatch(display->display); + clock_gettime(CLOCK_MONOTONIC, ¤t_time); + delta_time = current_time.tv_sec - start_time.tv_sec; + } destroy_window(window); destroy_display(display); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/clients/simple-dmabuf-v4l.c new/weston-10.0.2/clients/simple-dmabuf-v4l.c --- old/weston-10.0.0/clients/simple-dmabuf-v4l.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/clients/simple-dmabuf-v4l.c 2022-07-26 12:22:25.000000000 +0200 @@ -127,7 +127,7 @@ int data_offsets[VIDEO_MAX_PLANES]; }; -#define NUM_BUFFERS 3 +#define NUM_BUFFERS 4 struct window { struct display *display; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/clients/simple-egl.c new/weston-10.0.2/clients/simple-egl.c --- old/weston-10.0.0/clients/simple-egl.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/clients/simple-egl.c 2022-07-26 12:22:25.000000000 +0200 @@ -262,6 +262,19 @@ GLuint frag, vert; GLuint program; GLint status; + EGLBoolean ret; + + window->native = wl_egl_window_create(window->surface, + window->geometry.width, + window->geometry.height); + window->egl_surface = + weston_platform_create_egl_surface(window->display->egl.dpy, + window->display->egl.conf, + window->native, NULL); + + ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface, + window->egl_surface, window->display->egl.ctx); + assert(ret == EGL_TRUE); frag = create_shader(window, frag_shader_text, GL_FRAGMENT_SHADER); vert = create_shader(window, vert_shader_text, GL_VERTEX_SHADER); @@ -362,19 +375,9 @@ create_surface(struct window *window) { struct display *display = window->display; - EGLBoolean ret; window->surface = wl_compositor_create_surface(display->compositor); - window->native = - wl_egl_window_create(window->surface, - window->geometry.width, - window->geometry.height); - window->egl_surface = - weston_platform_create_egl_surface(display->egl.dpy, - display->egl.conf, - window->native, NULL); - window->xdg_surface = xdg_wm_base_get_xdg_surface(display->wm_base, window->surface); xdg_surface_add_listener(window->xdg_surface, @@ -389,21 +392,16 @@ xdg_toplevel_set_app_id(window->xdg_toplevel, "org.freedesktop.weston.simple-egl"); + if (window->fullscreen) + xdg_toplevel_set_fullscreen(window->xdg_toplevel, NULL); + else if (window->maximized) + xdg_toplevel_set_maximized(window->xdg_toplevel); + window->wait_for_configure = true; wl_surface_commit(window->surface); - ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface, - window->egl_surface, window->display->egl.ctx); - assert(ret == EGL_TRUE); - if (!window->frame_sync) eglSwapInterval(display->egl.dpy, 0); - - if (!display->wm_base) - return; - - if (window->fullscreen) - xdg_toplevel_set_fullscreen(window->xdg_toplevel, NULL); } static void @@ -806,6 +804,7 @@ fprintf(stderr, "Usage: simple-egl [OPTIONS]\n\n" " -d <us>\tBuffer swap delay in microseconds\n" " -f\tRun in fullscreen mode\n" + " -m\tRun in maximized mode\n" " -o\tCreate an opaque surface\n" " -s\tUse a 16 bpp EGL config\n" " -b\tDon't sync to compositor redraw (eglSwapInterval 0)\n" @@ -836,6 +835,8 @@ window.delay = atoi(argv[++i]); else if (strcmp("-f", argv[i]) == 0) window.fullscreen = 1; + else if (strcmp("-m", argv[i]) == 0) + window.maximized = 1; else if (strcmp("-o", argv[i]) == 0) window.opaque = 1; else if (strcmp("-s", argv[i]) == 0) @@ -864,7 +865,17 @@ init_egl(&display, &window); create_surface(&window); - init_gl(&window); + + /* we already have wait_for_configure set after create_surface() */ + while (running && ret != -1 && window.wait_for_configure) { + ret = wl_display_dispatch(display.display); + + /* wait until xdg_surface::configure acks the new dimensions */ + if (window.wait_for_configure) + continue; + + init_gl(&window); + } display.cursor_surface = wl_compositor_create_surface(display.compositor); @@ -874,17 +885,9 @@ sigint.sa_flags = SA_RESETHAND; sigaction(SIGINT, &sigint, NULL); - /* The mainloop here is a little subtle. Redrawing will cause - * EGL to read events so we can just call - * wl_display_dispatch_pending() to handle any events that got - * queued up as a side effect. */ while (running && ret != -1) { - if (window.wait_for_configure) { - ret = wl_display_dispatch(display.display); - } else { - ret = wl_display_dispatch_pending(display.display); - redraw(&window, NULL, 0); - } + ret = wl_display_dispatch_pending(display.display); + redraw(&window, NULL, 0); } fprintf(stderr, "simple-egl exiting\n"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/desktop-shell/shell.c new/weston-10.0.2/desktop-shell/shell.c --- old/weston-10.0.0/desktop-shell/shell.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/desktop-shell/shell.c 2022-07-26 12:22:25.000000000 +0200 @@ -101,6 +101,8 @@ struct weston_desktop_surface *desktop_surface; struct weston_view *view; + struct weston_surface *wsurface_anim_fade; + struct weston_view *wview_anim_fade; int32_t last_width, last_height; struct desktop_shell *shell; @@ -194,6 +196,10 @@ }; +static struct weston_view * +shell_fade_create_fade_out_view(struct shell_surface *shsurf, + struct weston_surface *surface); + static struct desktop_shell * shell_surface_get_shell(struct shell_surface *shsurf); @@ -261,10 +267,12 @@ wl_list_init(&shsurf_child->children_link); } wl_list_remove(&shsurf->children_link); + weston_desktop_surface_unlink_view(shsurf->view); + weston_view_destroy(shsurf->view); wl_signal_emit(&shsurf->destroy_signal, shsurf); + weston_surface_destroy(shsurf->wsurface_anim_fade); - weston_view_destroy(shsurf->view); if (shsurf->output_destroy_listener.notify) { wl_list_remove(&shsurf->output_destroy_listener.link); shsurf->output_destroy_listener.notify = NULL; @@ -877,7 +885,7 @@ } static void -desktop_shell_destroy_views_on_layer(struct weston_layer *layer); +desktop_shell_destroy_layer(struct weston_layer *layer); static void workspace_destroy(struct workspace *ws) @@ -892,7 +900,7 @@ if (ws->fsurf_back) focus_surface_destroy(ws->fsurf_back); - desktop_shell_destroy_views_on_layer(&ws->layer); + desktop_shell_destroy_layer(&ws->layer); free(ws); } @@ -1381,7 +1389,7 @@ int dx = wl_fixed_to_int(grab->touch->grab_x + move->dx); int dy = wl_fixed_to_int(grab->touch->grab_y + move->dy); - if (!shsurf || !move->active) + if (!shsurf || !shsurf->desktop_surface || !move->active) return; es = weston_desktop_surface_get_surface(shsurf->desktop_surface); @@ -1513,7 +1521,7 @@ int cx, cy; weston_pointer_move(pointer, event); - if (!shsurf) + if (!shsurf || !shsurf->desktop_surface) return; surface = weston_desktop_surface_get_surface(shsurf->desktop_surface); @@ -2253,8 +2261,8 @@ loop = wl_display_get_event_loop(shsurf->shell->compositor->wl_display); - if (weston_view_is_mapped(shsurf->view)) { - weston_view_unmap(shsurf->view); + if (weston_view_is_mapped(shsurf->wview_anim_fade)) { + weston_view_unmap(shsurf->wview_anim_fade); wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf); } } @@ -2364,7 +2372,6 @@ weston_desktop_surface_set_user_data(shsurf->desktop_surface, NULL); shsurf->desktop_surface = NULL; - weston_desktop_surface_unlink_view(shsurf->view); if (weston_surface_is_mapped(surface) && shsurf->shell->win_close_animation_type == ANIMATION_FADE) { @@ -2373,11 +2380,26 @@ pixman_region32_init(&surface->pending.input); pixman_region32_fini(&surface->input); pixman_region32_init(&surface->input); - weston_fade_run(shsurf->view, 1.0, 0.0, 300.0, + + /* its location might have changed, but also might've + * migrated to a different output, so re-compute this + * as the animation requires having the same output as + * the view */ + weston_view_set_output(shsurf->wview_anim_fade, + shsurf->view->output); + weston_view_set_position(shsurf->wview_anim_fade, + shsurf->view->geometry.x, + shsurf->view->geometry.y); + + weston_layer_entry_insert(&shsurf->view->layer_link, + &shsurf->wview_anim_fade->layer_link); + + /* unmap the "original" view */ + weston_view_unmap(shsurf->view); + weston_fade_run(shsurf->wview_anim_fade, 1.0, 0.0, 300.0, fade_out_done, shsurf); + return; - } else { - weston_surface_destroy(surface); } } @@ -2500,8 +2522,14 @@ if (!weston_surface_is_mapped(surface)) { map(shell, shsurf, sx, sy); surface->is_mapped = true; - if (shsurf->shell->win_close_animation_type == ANIMATION_FADE) - ++surface->ref_count; + /* as we need to survive the weston_surface destruction we'll + * need to take another reference */ + if (shsurf->shell->win_close_animation_type == ANIMATION_FADE) { + surface->ref_count++; + shsurf->wsurface_anim_fade = surface; + shsurf->wview_anim_fade = + shell_fade_create_fade_out_view(shsurf, surface); + } return; } @@ -3992,6 +4020,29 @@ return view; } +static struct weston_view * +shell_fade_create_fade_out_view(struct shell_surface *shsurf, + struct weston_surface *surface) +{ + struct weston_view *view; + struct weston_output *woutput; + + view = weston_view_create(surface); + if (!view) + return NULL; + + woutput = get_focused_output(surface->compositor); + /* set the initial position and output just in case we happen to not + * move it around and just destroy it */ + weston_view_set_output(view, woutput); + weston_view_set_position(view, + shsurf->view->geometry.x, + shsurf->view->geometry.y); + view->is_mapped = true; + + return view; +} + static void shell_fade(struct desktop_shell *shell, enum fade_type type) { @@ -4905,7 +4956,7 @@ } static void -desktop_shell_destroy_views_on_layer(struct weston_layer *layer) +desktop_shell_destroy_layer(struct weston_layer *layer) { struct weston_view *view, *view_next; @@ -4916,9 +4967,17 @@ * additional black_view created and added to its layer_link * fullscreen view. See shell_ensure_fullscreen_black_view() * - * As that black_view it is not a weston_desktop_surface - * we can't have a shsurf for it so we just destroy it like - * we do it in desktop_surface_removed() */ + * Note that we do not choose to destroy all other potential + * views we find in the layer, but instead we explicitly verify + * if the view in question was explicitly created by + * desktop-shell, rather than libweston-desktop (in + * desktop_surface_added()). + * + * This is particularly important because libweston-desktop + * could create additional views, which are managed implicitly, + * but which are still being added to the layer list. + * + */ if (shsurf) desktop_shell_destroy_surface(shsurf); else @@ -4970,12 +5029,12 @@ workspace_destroy(*ws); wl_array_release(&shell->workspaces.array); - desktop_shell_destroy_views_on_layer(&shell->panel_layer); - desktop_shell_destroy_views_on_layer(&shell->background_layer); - desktop_shell_destroy_views_on_layer(&shell->lock_layer); - desktop_shell_destroy_views_on_layer(&shell->input_panel_layer); - desktop_shell_destroy_views_on_layer(&shell->minimized_layer); - desktop_shell_destroy_views_on_layer(&shell->fullscreen_layer); + desktop_shell_destroy_layer(&shell->panel_layer); + desktop_shell_destroy_layer(&shell->background_layer); + desktop_shell_destroy_layer(&shell->lock_layer); + desktop_shell_destroy_layer(&shell->input_panel_layer); + desktop_shell_destroy_layer(&shell->minimized_layer); + desktop_shell_destroy_layer(&shell->fullscreen_layer); free(shell->client); free(shell); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/kiosk-shell/kiosk-shell.c new/weston-10.0.2/kiosk-shell/kiosk-shell.c --- old/weston-10.0.0/kiosk-shell/kiosk-shell.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/kiosk-shell/kiosk-shell.c 2022-07-26 12:22:25.000000000 +0200 @@ -173,8 +173,10 @@ app_id = weston_desktop_surface_get_app_id(shsurf->desktop_surface); if (app_id) { wl_list_for_each(shoutput, &shsurf->shell->output_list, link) { - if (kiosk_shell_output_has_app_id(shoutput, app_id)) + if (kiosk_shell_output_has_app_id(shoutput, app_id)) { + shsurf->appid_output_assigned = true; return shoutput->output; + } } } @@ -354,6 +356,7 @@ shsurf->desktop_surface = desktop_surface; shsurf->view = view; shsurf->shell = shell; + shsurf->appid_output_assigned = false; weston_desktop_surface_set_user_data(desktop_surface, shsurf); @@ -387,8 +390,10 @@ /* removes it from the normal_layer and move it to inactive * one, without occluding the top-level window if the new one - * is a child to that */ - if (!shsurf->parent) { + * is a child to that. Also, do not occlude another view + * (currently focused one) on a different output when activating + * a new one. */ + if (!shsurf->parent && (shsurf->output == current_focus->output)) { weston_layer_entry_remove(¤t_focus->view->layer_link); weston_layer_entry_insert(&shsurf->shell->inactive_layer.view_list, ¤t_focus->view->layer_link); @@ -645,12 +650,18 @@ struct weston_view *top_view = NULL; struct weston_view *view; + /* we need to take into account that the surface being destroyed it not * always the same as the focus_surface, which could result in picking * and *activating* the wrong window, so avoid returning a view for * that case. A particular case is when a top-level child window, would - * pick a parent window below the focused_surface. */ - if (focused_surface != shsurf->view->surface) + * pick a parent window below the focused_surface. + * + * Apply that only on the same output to avoid incorrectly returning an + * invalid/empty view, which could happen if the view being destroyed + * is on a output different than the focused_surface output */ + if (focused_surface && focused_surface != shsurf->view->surface && + shsurf->output == focused_surface->output) return top_view; wl_list_for_each(view, &layer->view_list.link, layer_link.link) { @@ -660,6 +671,10 @@ if (!view->is_mapped || view == shsurf->view) continue; + /* pick views only on the same output */ + if (view->output != shsurf->output) + continue; + view_shsurf = get_kiosk_shell_surface(view->surface); if (!view_shsurf) continue; @@ -721,6 +736,8 @@ weston_desktop_surface_get_user_data(desktop_surface); struct weston_surface *surface = weston_desktop_surface_get_surface(desktop_surface); + const char *app_id = + weston_desktop_surface_get_app_id(desktop_surface); bool is_resized; bool is_fullscreen; @@ -729,6 +746,24 @@ if (surface->width == 0) return; + if (!shsurf->appid_output_assigned && app_id) { + struct weston_output *output = NULL; + + /* reset previous output being set in _added() as the output is + * being cached */ + shsurf->output = NULL; + output = kiosk_shell_surface_find_best_output(shsurf); + + kiosk_shell_surface_set_output(shsurf, output); + weston_desktop_surface_set_size(shsurf->desktop_surface, + shsurf->output->width, + shsurf->output->height); + /* even if we couldn't find an appid set for a particular + * output still flag the shsurf as to a avoid changing the + * output every time */ + shsurf->appid_output_assigned = true; + } + /* TODO: When the top-level surface is committed with a new size after an * output resize, sometimes the view appears scaled. What state are we not * updating? diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/kiosk-shell/kiosk-shell.h new/weston-10.0.2/kiosk-shell/kiosk-shell.h --- old/weston-10.0.0/kiosk-shell/kiosk-shell.h 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/kiosk-shell/kiosk-shell.h 2022-07-26 12:22:25.000000000 +0200 @@ -73,6 +73,8 @@ int32_t x; int32_t y; } xwayland; + + bool appid_output_assigned; }; struct kiosk_shell_seat { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/libweston/backend-drm/drm-internal.h new/weston-10.0.2/libweston/backend-drm/drm-internal.h --- old/weston-10.0.0/libweston/backend-drm/drm-internal.h 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/libweston/backend-drm/drm-internal.h 2022-07-26 12:22:25.000000000 +0200 @@ -236,6 +236,7 @@ FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE = (1 << 1), FAILURE_REASONS_DMABUF_MODIFIER_INVALID = (1 << 2), FAILURE_REASONS_ADD_FB_FAILED = (1 << 3), + FAILURE_REASONS_GBM_BO_IMPORT_FAILED = (1 << 4) }; /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/libweston/backend-drm/fb.c new/weston-10.0.2/libweston/backend-drm/fb.c --- old/weston-10.0.0/libweston/backend-drm/fb.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/libweston/backend-drm/fb.c 2022-07-26 12:22:25.000000000 +0200 @@ -276,8 +276,12 @@ fb->bo = gbm_bo_import(backend->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_mod, GBM_BO_USE_SCANOUT); - if (!fb->bo) + if (!fb->bo) { + if (try_view_on_plane_failure_reasons) + *try_view_on_plane_failure_reasons |= + FAILURE_REASONS_GBM_BO_IMPORT_FAILED; goto err_free; + } fb->width = dmabuf->attributes.width; fb->height = dmabuf->attributes.height; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/libweston/backend-drm/state-propose.c new/weston-10.0.2/libweston/backend-drm/state-propose.c --- old/weston-10.0.0/libweston/backend-drm/state-propose.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/libweston/backend-drm/state-propose.c 2022-07-26 12:22:25.000000000 +0200 @@ -602,7 +602,8 @@ if (try_view_on_plane_failure_reasons & (FAILURE_REASONS_ADD_FB_FAILED | FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE | - FAILURE_REASONS_DMABUF_MODIFIER_INVALID)) + FAILURE_REASONS_DMABUF_MODIFIER_INVALID | + FAILURE_REASONS_GBM_BO_IMPORT_FAILED)) action_needed |= ACTION_NEEDED_ADD_SCANOUT_TRANCHE; assert(action_needed != (ACTION_NEEDED_REMOVE_SCANOUT_TRANCHE | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/libweston/compositor.c new/weston-10.0.2/libweston/compositor.c --- old/weston-10.0.0/libweston/compositor.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/libweston/compositor.c 2022-07-26 12:22:25.000000000 +0200 @@ -2306,6 +2306,10 @@ struct weston_pointer_constraint *constraint, *next_constraint; struct weston_paint_node *pnode, *pntmp; + if (!surface) + return; + + assert(surface->ref_count > 0); if (--surface->ref_count > 0) return; @@ -4044,54 +4048,22 @@ surface_damage_buffer }; -static int -create_surface_dmabuf_feedback(struct weston_compositor *ec, - struct weston_surface *surface) -{ - struct weston_dmabuf_feedback_tranche *tranche; - dev_t main_device = ec->default_dmabuf_feedback->main_device; - uint32_t flags = 0; - - surface->dmabuf_feedback = weston_dmabuf_feedback_create(main_device); - if (!surface->dmabuf_feedback) - return -1; - - tranche = weston_dmabuf_feedback_tranche_create(surface->dmabuf_feedback, - ec->dmabuf_feedback_format_table, - main_device, flags, - RENDERER_PREF); - if (!tranche) { - weston_dmabuf_feedback_destroy(surface->dmabuf_feedback); - surface->dmabuf_feedback = NULL; - return -1; - } - - return 0; -} - static void compositor_create_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id) { struct weston_compositor *ec = wl_resource_get_user_data(resource); struct weston_surface *surface; - int ret; surface = weston_surface_create(ec); if (surface == NULL) goto err; - if (ec->default_dmabuf_feedback) { - ret = create_surface_dmabuf_feedback(ec, surface); - if (ret < 0) - goto err_dmabuf_feedback; - } - surface->resource = wl_resource_create(client, &wl_surface_interface, wl_resource_get_version(resource), id); if (surface->resource == NULL) - goto err_dmabuf_feedback; + goto err_res; wl_resource_set_implementation(surface->resource, &surface_interface, surface, destroy_surface); @@ -4099,7 +4071,7 @@ return; -err_dmabuf_feedback: +err_res: weston_surface_destroy(surface); err: wl_resource_post_no_memory(resource); @@ -4211,6 +4183,11 @@ &surface->pending.damage_surface); pixman_region32_clear(&surface->pending.damage_surface); + pixman_region32_union(&sub->cached.damage_buffer, + &sub->cached.damage_buffer, + &surface->pending.damage_buffer); + pixman_region32_clear(&surface->pending.damage_buffer); + if (surface->pending.newly_attached) { sub->cached.newly_attached = 1; weston_surface_state_set_buffer(&sub->cached, @@ -4233,8 +4210,6 @@ sub->cached.sx += surface->pending.sx; sub->cached.sy += surface->pending.sy; - apply_damage_buffer(&sub->cached.damage_surface, surface, &surface->pending); - sub->cached.buffer_viewport.changed |= surface->pending.buffer_viewport.changed; sub->cached.buffer_viewport.buffer = @@ -4361,7 +4336,7 @@ */ if (!weston_surface_is_mapped(surface)) { - surface->is_mapped = true; + surface->is_mapped = surface->buffer_ref.buffer != NULL; /* Cannot call weston_view_update_transform(), * because that would call it also for the parent surface, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/libweston/linux-dmabuf.c new/weston-10.0.2/libweston/linux-dmabuf.c --- old/weston-10.0.0/libweston/linux-dmabuf.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/libweston/linux-dmabuf.c 2022-07-26 12:22:25.000000000 +0200 @@ -684,6 +684,7 @@ wl_resource_for_each_safe(res, res_tmp, &dmabuf_feedback->resource_list) { wl_list_remove(wl_resource_get_link(res)); wl_list_init(wl_resource_get_link(res)); + wl_resource_set_user_data(res, NULL); } free(dmabuf_feedback); @@ -786,6 +787,7 @@ { struct wl_resource *res; + assert(!wl_list_empty(&dmabuf_feedback->resource_list)); wl_resource_for_each(res, &dmabuf_feedback->resource_list) weston_dmabuf_feedback_send(dmabuf_feedback, format_table, res, false); @@ -794,7 +796,16 @@ static void dmabuf_feedback_resource_destroy(struct wl_resource *resource) { + struct weston_surface *surface = + wl_resource_get_user_data(resource); + wl_list_remove(wl_resource_get_link(resource)); + + if (surface && + wl_list_empty(&surface->dmabuf_feedback->resource_list)) { + weston_dmabuf_feedback_destroy(surface->dmabuf_feedback); + surface->dmabuf_feedback = NULL; + } } static void @@ -810,7 +821,8 @@ static struct wl_resource * dmabuf_feedback_resource_create(struct wl_resource *dmabuf_resource, - struct wl_client *client, uint32_t dmabuf_feedback_id) + struct wl_client *client, uint32_t dmabuf_feedback_id, + struct weston_surface *surface) { struct wl_resource *dmabuf_feedback_res; uint32_t version; @@ -826,7 +838,7 @@ wl_list_init(wl_resource_get_link(dmabuf_feedback_res)); wl_resource_set_implementation(dmabuf_feedback_res, &zwp_linux_dmabuf_feedback_implementation, - NULL, dmabuf_feedback_resource_destroy); + surface, dmabuf_feedback_resource_destroy); return dmabuf_feedback_res; } @@ -842,7 +854,8 @@ dmabuf_feedback_resource = dmabuf_feedback_resource_create(dmabuf_resource, - client, dmabuf_feedback_id); + client, dmabuf_feedback_id, + NULL); if (!dmabuf_feedback_resource) { wl_resource_post_no_memory(dmabuf_resource); return; @@ -853,22 +866,55 @@ dmabuf_feedback_resource, true); } +static int +create_surface_dmabuf_feedback(struct weston_compositor *ec, + struct weston_surface *surface) +{ + struct weston_dmabuf_feedback_tranche *tranche; + dev_t main_device = ec->default_dmabuf_feedback->main_device; + uint32_t flags = 0; + + surface->dmabuf_feedback = weston_dmabuf_feedback_create(main_device); + if (!surface->dmabuf_feedback) + return -1; + + tranche = weston_dmabuf_feedback_tranche_create(surface->dmabuf_feedback, + ec->dmabuf_feedback_format_table, + main_device, flags, + RENDERER_PREF); + if (!tranche) { + weston_dmabuf_feedback_destroy(surface->dmabuf_feedback); + surface->dmabuf_feedback = NULL; + return -1; + } + + return 0; +} + static void linux_dmabuf_get_per_surface_feedback(struct wl_client *client, struct wl_resource *dmabuf_resource, uint32_t dmabuf_feedback_id, struct wl_resource *surface_resource) { + struct weston_compositor *compositor = + wl_resource_get_user_data(dmabuf_resource); struct weston_surface *surface = wl_resource_get_user_data(surface_resource); struct wl_resource *dmabuf_feedback_resource; + int ret; dmabuf_feedback_resource = dmabuf_feedback_resource_create(dmabuf_resource, - client, dmabuf_feedback_id); - if (!dmabuf_feedback_resource) { - wl_resource_post_no_memory(dmabuf_resource); - return; + client, dmabuf_feedback_id, + surface); + if (!dmabuf_feedback_resource) + goto err; + + if (!surface->dmabuf_feedback) { + ret = create_surface_dmabuf_feedback(compositor, surface); + if (ret < 0) + goto err_feedback; } /* Surface dma-buf feedback is dynamic and may need to be resent to @@ -879,6 +925,13 @@ weston_dmabuf_feedback_send(surface->dmabuf_feedback, surface->compositor->dmabuf_feedback_format_table, dmabuf_feedback_resource, true); + return; + +err_feedback: + wl_resource_set_user_data(dmabuf_feedback_resource, NULL); + wl_resource_destroy(dmabuf_feedback_resource); +err: + wl_resource_post_no_memory(dmabuf_resource); } /** Get the linux_dmabuf_buffer from a wl_buffer resource diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/libweston/renderer-gl/fragment.glsl new/weston-10.0.2/libweston/renderer-gl/fragment.glsl --- old/weston-10.0.0/libweston/renderer-gl/fragment.glsl 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/libweston/renderer-gl/fragment.glsl 2022-07-26 12:22:25.000000000 +0200 @@ -67,6 +67,9 @@ compile_const bool c_green_tint = DEF_GREEN_TINT; compile_const int c_color_pre_curve = DEF_COLOR_PRE_CURVE; +compile_const bool c_need_color_pipeline = + c_color_pre_curve != SHADER_COLOR_CURVE_IDENTITY; + vec4 yuva2rgba(vec4 yuva) { @@ -202,9 +205,6 @@ vec4 color_pipeline(vec4 color) { - /* View alpha (opacity) */ - color.a *= alpha; - color.rgb = color_pre_curve(color.rgb); return color; @@ -218,18 +218,35 @@ /* Electrical (non-linear) RGBA values, may be premult or not */ color = sample_input_texture(); - /* Ensure straight alpha */ - if (c_input_is_premult) { - if (color.a == 0.0) - color.rgb = vec3(0, 0, 0); - else - color.rgb *= 1.0 / color.a; - } + if (c_need_color_pipeline) { + /* Ensure straight alpha */ + if (c_input_is_premult) { + if (color.a == 0.0) + color.rgb = vec3(0, 0, 0); + else + color.rgb *= 1.0 / color.a; + } + + color = color_pipeline(color); - color = color_pipeline(color); + /* View alpha (opacity) */ + color.a *= alpha; - /* pre-multiply for blending */ - color.rgb *= color.a; + /* pre-multiply for blending */ + color.rgb *= color.a; + } else { + /* Fast path for disabled color management */ + + if (c_input_is_premult) { + /* View alpha (opacity) */ + color *= alpha; + } else { + /* View alpha (opacity) */ + color.a *= alpha; + /* pre-multiply for blending */ + color.rgb *= color.a; + } + } if (c_green_tint) color = vec4(0.0, 0.3, 0.0, 0.2) + color * 0.8; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/libweston-desktop/xdg-shell.c new/weston-10.0.2/libweston-desktop/xdg-shell.c --- old/weston-10.0.0/libweston-desktop/xdg-shell.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/libweston-desktop/xdg-shell.c 2022-07-26 12:22:25.000000000 +0200 @@ -713,7 +713,7 @@ wl_resource_post_error(client_resource, XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, - "xdg_surface buffer (%" PRIi32 " x %" PRIi32 ") " + "xdg_surface geometry (%" PRIi32 " x %" PRIi32 ") " "does not match the configured maximized state (%" PRIi32 " x %" PRIi32 ")", geometry.width, geometry.height, toplevel->next.size.width, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/meson.build new/weston-10.0.2/meson.build --- old/weston-10.0.0/meson.build 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/meson.build 2022-07-26 12:22:25.000000000 +0200 @@ -1,6 +1,6 @@ project('weston', 'c', - version: '10.0.0', + version: '10.0.2', default_options: [ 'warning_level=3', 'c_std=gnu99', @@ -121,7 +121,7 @@ backend_default = get_option('backend-default') if backend_default == 'auto' - foreach b : [ 'headless', 'fbdev', 'x11', 'wayland', 'drm' ] + foreach b : [ 'headless', 'x11', 'wayland', 'drm' ] if get_option('backend-' + b) backend_default = b endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/tests/devices-test.c new/weston-10.0.2/tests/devices-test.c --- old/weston-10.0.0/tests/devices-test.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/tests/devices-test.c 2022-07-26 12:22:25.000000000 +0200 @@ -36,6 +36,8 @@ compositor_setup_defaults(&setup); + setup.shell = SHELL_TEST_DESKTOP; + return weston_test_harness_execute_as_client(harness, &setup); } DECLARE_FIXTURE_SETUP(fixture_setup); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/tests/ivi-layout-test-plugin.c new/weston-10.0.2/tests/ivi-layout-test-plugin.c --- old/weston-10.0.0/tests/ivi-layout-test-plugin.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/tests/ivi-layout-test-plugin.c 2022-07-26 12:22:25.000000000 +0200 @@ -53,7 +53,7 @@ static void runner_func_##name(struct test_context *); \ \ const struct runner_test runner_test_##name \ - __attribute__ ((section ("plugin_test_section"))) = \ + __attribute__ ((used, section ("plugin_test_section"))) = \ { \ #name, runner_func_##name \ }; \ Binary files old/weston-10.0.0/tests/reference/subsurface_empty_mapping-00.png and new/weston-10.0.2/tests/reference/subsurface_empty_mapping-00.png differ Binary files old/weston-10.0.0/tests/reference/subsurface_empty_mapping-01.png and new/weston-10.0.2/tests/reference/subsurface_empty_mapping-01.png differ Binary files old/weston-10.0.0/tests/reference/subsurface_sync_damage_buffer-00.png and new/weston-10.0.2/tests/reference/subsurface_sync_damage_buffer-00.png differ Binary files old/weston-10.0.0/tests/reference/subsurface_sync_damage_buffer-01.png and new/weston-10.0.2/tests/reference/subsurface_sync_damage_buffer-01.png differ Binary files old/weston-10.0.0/tests/reference/subsurface_sync_damage_buffer-02.png and new/weston-10.0.2/tests/reference/subsurface_sync_damage_buffer-02.png differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weston-10.0.0/tests/subsurface-shot-test.c new/weston-10.0.2/tests/subsurface-shot-test.c --- old/weston-10.0.0/tests/subsurface-shot-test.c 2022-02-01 22:59:57.000000000 +0100 +++ new/weston-10.0.2/tests/subsurface-shot-test.c 2022-07-26 12:22:25.000000000 +0200 @@ -117,7 +117,7 @@ buf = create_shm_buffer_a8r8g8b8(client, width, height); fill_image_with_color(buf->image, color); wl_surface_attach(surface, buf->proxy, 0, 0); - wl_surface_damage(surface, 0, 0, width, height); + wl_surface_damage_buffer(surface, 0, 0, width, height); wl_surface_commit(surface); return buf; @@ -213,3 +213,199 @@ wl_subcompositor_destroy(subco); client_destroy(client); } + +TEST(subsurface_sync_damage_buffer) +{ + struct client *client; + struct wl_subcompositor *subco; + struct buffer *bufs[2] = { 0 }; + struct wl_surface *surf[2] = { 0 }; + struct wl_subsurface *sub[2] = { 0 }; + struct rectangle clip = { 40, 40, 280, 200 }; + int fail = 0; + unsigned i; + pixman_color_t red; + pixman_color_t blue; + pixman_color_t green; + + color_rgb888(&red, 255, 0, 0); + color_rgb888(&blue, 0, 0, 255); + color_rgb888(&green, 0, 255, 0); + + client = create_client_and_test_surface(100, 50, 100, 100); + assert(client); + subco = get_subcompositor(client); + + /* move the pointer clearly away from our screenshooting area */ + weston_test_move_pointer(client->test->weston_test, 0, 1, 0, 2, 30); + + /* make the parent surface red */ + surf[0] = client->surface->wl_surface; + client->surface->wl_surface = NULL; /* we stole it and destroy it */ + bufs[0] = surface_commit_color(client, surf[0], &red, 100, 100); + /* sub[0] is not used */ + + fail += check_screen(client, "subsurface_sync_damage_buffer", 0, &clip, 0); + + /* create a blue sub-surface above red */ + surf[1] = wl_compositor_create_surface(client->wl_compositor); + sub[1] = wl_subcompositor_get_subsurface(subco, surf[1], surf[0]); + bufs[1] = surface_commit_color(client, surf[1], &blue, 100, 100); + + wl_subsurface_set_position(sub[1], 20, 20); + wl_surface_commit(surf[0]); + + fail += check_screen(client, "subsurface_sync_damage_buffer", 1, &clip, 1); + + buffer_destroy(bufs[1]); + bufs[1] = surface_commit_color(client, surf[1], &green, 100, 100); + wl_surface_commit(surf[0]); + + fail += check_screen(client, "subsurface_sync_damage_buffer", 2, &clip, 2); + + assert(fail == 0); + + for (i = 0; i < ARRAY_LENGTH(sub); i++) + if (sub[i]) + wl_subsurface_destroy(sub[i]); + + for (i = 0; i < ARRAY_LENGTH(surf); i++) + if (surf[i]) + wl_surface_destroy(surf[i]); + + for (i = 0; i < ARRAY_LENGTH(bufs); i++) + if (bufs[i]) + buffer_destroy(bufs[i]); + + wl_subcompositor_destroy(subco); + client_destroy(client); +} + +TEST(subsurface_empty_mapping) +{ + struct client *client; + struct wl_subcompositor *subco; + struct wp_viewporter *viewporter; + struct buffer *bufs[3] = { 0 }; + struct wl_surface *surf[3] = { 0 }; + struct wl_subsurface *sub[3] = { 0 }; + struct wp_viewport *viewport; + struct rectangle clip = { 40, 40, 280, 200 }; + int fail = 0; + unsigned i; + pixman_color_t red; + pixman_color_t blue; + pixman_color_t green; + + color_rgb888(&red, 255, 0, 0); + color_rgb888(&blue, 0, 0, 255); + color_rgb888(&green, 0, 255, 0); + + client = create_client_and_test_surface(100, 50, 100, 100); + assert(client); + subco = get_subcompositor(client); + viewporter = bind_to_singleton_global(client, + &wp_viewporter_interface, 1); + + /* move the pointer clearly away from our screenshooting area */ + weston_test_move_pointer(client->test->weston_test, 0, 1, 0, 2, 30); + + /* make the parent surface red */ + surf[0] = client->surface->wl_surface; + client->surface->wl_surface = NULL; /* we stole it and destroy it */ + bufs[0] = surface_commit_color(client, surf[0], &red, 100, 100); + /* sub[0] is not used */ + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 0); + + /* create an empty subsurface on top */ + surf[1] = wl_compositor_create_surface(client->wl_compositor); + sub[1] = wl_subcompositor_get_subsurface(subco, surf[1], surf[0]); + wl_subsurface_set_desync (sub[1]); + + wl_subsurface_set_position(sub[1], 20, 20); + wl_surface_commit(surf[0]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 1); + + /* create a green subsurface on top */ + surf[2] = wl_compositor_create_surface(client->wl_compositor); + sub[2] = wl_subcompositor_get_subsurface(subco, surf[2], surf[1]); + wl_subsurface_set_desync (sub[2]); + bufs[2] = surface_commit_color(client, surf[2], &green, 100, 100); + + wl_subsurface_set_position(sub[2], 20, 20); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 2); + + wl_surface_attach(surf[1], NULL, 0, 0); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 3); + + wl_surface_set_buffer_scale (surf[1], 1); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 4); + + viewport = wp_viewporter_get_viewport(viewporter, surf[1]); + wp_viewport_set_destination(viewport, 5, 5); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 5); + + wp_viewport_set_destination(viewport, -1, -1); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 6); + + /* map the previously empty middle surface with a blue buffer */ + bufs[1] = surface_commit_color(client, surf[1], &blue, 100, 100); + + fail += check_screen(client, "subsurface_empty_mapping", 1, &clip, 7); + + /* try to trigger a recomputation of the buffer size with the + * shm-buffer potentially being released already */ + wl_surface_set_buffer_scale (surf[1], 1); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 1, &clip, 8); + + /* try more */ + wp_viewport_set_destination(viewport, 100, 100); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 1, &clip, 9); + + /* unmap the middle surface again to ensure recursive unmapping */ + wl_surface_attach(surf[1], NULL, 0, 0); + wl_surface_commit(surf[1]); + + fail += check_screen(client, "subsurface_empty_mapping", 0, &clip, 10); + + /* remap middle surface to ensure recursive mapping */ + bufs[1] = surface_commit_color(client, surf[1], &blue, 100, 100); + + fail += check_screen(client, "subsurface_empty_mapping", 1, &clip, 11); + + assert(fail == 0); + + wp_viewport_destroy(viewport); + + for (i = 0; i < ARRAY_LENGTH(sub); i++) + if (sub[i]) + wl_subsurface_destroy(sub[i]); + + for (i = 0; i < ARRAY_LENGTH(surf); i++) + if (surf[i]) + wl_surface_destroy(surf[i]); + + for (i = 0; i < ARRAY_LENGTH(bufs); i++) + if (bufs[i]) + buffer_destroy(bufs[i]); + + wp_viewporter_destroy(viewporter); + wl_subcompositor_destroy(subco); + client_destroy(client); +}
