From b0c5db9f5aa500dc3568cc6fe68493df98794d4d Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sat, 9 Feb 2019 15:52:40 +0000 Subject: [PATCH] Let old/new backends co-exist Now both the old and the new backends are compiled in, the user can choose which one to use with a command line switch. Lower the barrier for testing. Signed-off-by: Yuxuan Shui --- .circleci/config.yml | 29 +++++----------- man/compton.1.asciidoc | 3 ++ meson_options.txt | 2 -- src/backend/backend.h | 2 +- src/backend/meson.build | 5 +-- src/compton.c | 73 +++++++++++++++++++++++++++++++++++++---- src/compton.h | 1 + src/config.h | 7 ++-- src/options.c | 2 ++ src/win.c | 43 ++++++++++++++++++++---- 10 files changed, 123 insertions(+), 44 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7eff4eb..5d8af5e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,57 +43,46 @@ jobs: <<: *defaults steps: - build: - build-config: -Dbuild_docs=true -Dnew_backends=true + build-config: -Dbuild_docs=true minimal: <<: *defaults steps: - build: - build-config: -Dopengl=false -Ddbus=false -Dregex=false -Dconfig_file=false -Dnew_backends=true + build-config: -Dopengl=false -Ddbus=false -Dregex=false -Dconfig_file=false nogl: <<: *defaults steps: - build: - build-config: -Dopengl=false -Dnew_backends=true + build-config: -Dopengl=false noregex: <<: *defaults steps: - build: - build-config: -Dregex=false -Dnew_backends=true + build-config: -Dregex=false clang_basic: <<: *defaults steps: - build: cc: clang-6.0 - build-config: -Dnew_backends=true + build-config: clang_minimal: <<: *defaults steps: - build: cc: clang-6.0 - build-config: -Dopengl=false -Ddbus=false -Dregex=false -Dconfig_file=false -Dnew_backends=true + build-config: -Dopengl=false -Ddbus=false -Dregex=false -Dconfig_file=false clang_nogl: <<: *defaults steps: - build: cc: clang-6.0 - build-config: -Dopengl=false -Dnew_backends=true + build-config: -Dopengl=false clang_noregex: <<: *defaults steps: - build: cc: clang-6.0 - build-config: -Dregex=false -Dnew_backends=true - clang_basic_nonew: - <<: *defaults - steps: - - build: - cc: clang-6.0 - build-config: - basic_nonew: - <<: *defaults - steps: - - build: - build-config: + build-config: -Dregex=false workflows: all_builds: @@ -104,8 +93,6 @@ workflows: - clang_minimal - nogl - clang_nogl - - clang_basic_nonew - - basic_nonew # - test-xvfb # vim: set sw=2 ts=8 et: diff --git a/man/compton.1.asciidoc b/man/compton.1.asciidoc index dc9d673..9f78e40 100644 --- a/man/compton.1.asciidoc +++ b/man/compton.1.asciidoc @@ -76,6 +76,9 @@ OPTIONS *--log-file*:: Set the log file. If *--log-file* is never specified, logs will be written to stderr. Otherwise, logs will to writeen to the given file, though some of the early logs might still be written to the stderr. When setting this option from the config file, it is recommended to use an absolute path. +*--experimental-backends*:: + Use the new, reimplemented version of the backends. The new backends are HIGHLY UNSTABLE at this point, you have been warned. This option is not available in the config file. + *--show-all-xerrors*:: Show all X errors (for debugging). diff --git a/meson_options.txt b/meson_options.txt index 1672344..95292d1 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -11,6 +11,4 @@ option('xrescheck', type: 'boolean', value: false, description: 'Enable X resour option('build_docs', type: 'boolean', value: false, description: 'Build documentation and man pages') -option('new_backends', type: 'boolean', value: false, description: 'Does not really do anything right now') - option('modularize', type: 'boolean', value: false, description: 'Build with clang\'s module system') diff --git a/src/backend/backend.h b/src/backend/backend.h index 362af8a..acbbade 100644 --- a/src/backend/backend.h +++ b/src/backend/backend.h @@ -115,7 +115,7 @@ typedef struct backend_info { void *(*prepare_win)(void *backend_data, session_t *ps, win *w) __attribute__((nonnull(1, 2, 3))); - /// Free resources allocated by prepare() + /// Free resources allocated by prepare_win() void (*release_win)(void *backend_data, session_t *ps, win *w, void *win_data) __attribute__((nonnull(1, 2, 3))); diff --git a/src/backend/meson.build b/src/backend/meson.build index 0657686..6cd8e94 100644 --- a/src/backend/meson.build +++ b/src/backend/meson.build @@ -1,8 +1,5 @@ # enable xrender -srcs += [ files('backend_common.c') ] -if get_option('new_backends') - srcs += [ files('xrender.c', 'backend.c') ] -endif +srcs += [ files('backend_common.c', 'xrender.c', 'backend.c') ] # enable opengl if get_option('opengl') diff --git a/src/compton.c b/src/compton.c index 630106a..6bb6b33 100644 --- a/src/compton.c +++ b/src/compton.c @@ -46,6 +46,7 @@ #include "types.h" #include "c2.h" #include "log.h" +#include "backend/backend.h" #ifdef CONFIG_DBUS #include "dbus.h" #endif @@ -738,6 +739,7 @@ repair_win(session_t *ps, win *w) { add_damage(ps, &parts); pixman_region32_fini(&parts); } + static void restack_win(session_t *ps, win *w, xcb_window_t new_above) { xcb_window_t old_above; @@ -802,8 +804,17 @@ restack_win(session_t *ps, win *w, xcb_window_t new_above) { void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) { // On root window changes + auto root_change_fn = backend_list[ps->o.backend]->root_change; if (ce->window == ps->root) { - free_paint(ps, &ps->tgt_buffer); + if (ps->o.experimental_backends) { + if (!root_change_fn) { + // deinit/reinit backend if the backend cannot handle root change + backend_list[ps->o.backend]->deinit(ps->backend_data, ps); + ps->backend_data = NULL; + } + } else { + free_paint(ps, &ps->tgt_buffer); + } ps->root_width = ce->width; ps->root_height = ce->height; @@ -838,7 +849,13 @@ configure_win(session_t *ps, xcb_configure_notify_event_t *ce) { if (BKEND_GLX == ps->o.backend) glx_on_root_change(ps); #endif - + if (ps->o.experimental_backends) { + if (root_change_fn) { + root_change_fn(ps->backend_data, ps); + } else { + ps->backend_data = backend_list[ps->o.backend]->init(ps); + } + } force_repaint(ps); return; @@ -1948,11 +1965,26 @@ redir_start(session_t *ps) { // Map overlay window. Done firstly according to this: // https://bugzilla.gnome.org/show_bug.cgi?id=597014 - if (ps->overlay) + if (ps->overlay) { xcb_map_window(ps->c, ps->overlay); + } xcb_composite_redirect_subwindows(ps->c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); + x_sync(ps->c); + + if (ps->o.experimental_backends) { + // Reinitialize win_data + backend_info_t *bi = backend_list[ps->o.backend]; + assert(bi); + ps->backend_data = bi->init(ps); + for (win *w = ps->list; w; w = w->next) { + if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) { + w->win_data = bi->prepare_win(ps->backend_data, ps, w); + } + } + } + /* // Unredirect GL context window as this may have an effect on VSync: // < http://dri.freedesktop.org/wiki/CompositeSwap > @@ -1979,6 +2011,7 @@ static void redir_stop(session_t *ps) { if (ps->redirected) { log_debug("Screen unredirected."); + backend_info_t *bi = backend_list[ps->o.backend]; // Destroy all Pictures as they expire once windows are unredirected // If we don't destroy them here, looks like the resources are just // kept inaccessible somehow @@ -1992,7 +2025,18 @@ redir_stop(session_t *ps) { } // `w` might be freed by win_check_fade_finished - if (w) { + if (!w) { + continue; + } + if (ps->o.experimental_backends) { + assert(bi); + if (w->state == WSTATE_MAPPED) { + bi->release_win(ps->backend_data, ps, w, w->win_data); + w->win_data = NULL; + } else { + assert(!w->win_data); + } + } else { free_paint(ps, &w->paint); } } @@ -2002,6 +2046,12 @@ redir_stop(session_t *ps) { if (ps->overlay) xcb_unmap_window(ps->c, ps->overlay); + if (ps->o.experimental_backends) { + // deinit backend + bi->deinit(ps->backend_data, ps); + ps->backend_data = NULL; + } + // Must call XSync() here x_sync(ps->c); @@ -2079,7 +2129,11 @@ _draw_callback(EV_P_ session_t *ps, int revents) { // If the screen is unredirected, free all_damage to stop painting if (ps->redirected && ps->o.stoppaint_force != ON) { static int paint = 0; - paint_all(ps, t, false); + if (ps->o.experimental_backends) { + paint_all_new(ps, t, false); + } else { + paint_all(ps, t, false); + } paint++; if (ps->o.benchmark && paint >= ps->o.benchmark) @@ -2836,8 +2890,6 @@ session_destroy(session_t *ps) { free(ps->o.glx_fshader_win_str); free_xinerama_info(ps); - deinit_render(ps); - #ifdef CONFIG_VSYNC_DRM // Close file opened for DRM VSync if (ps->drm_fd >= 0) { @@ -2863,6 +2915,13 @@ session_destroy(session_t *ps) { ps->reg_win = XCB_NONE; } + if (ps->o.experimental_backends) { + // backend is deinitialized in redir_stop + assert(ps->backend_data == NULL); + } else { + deinit_render(ps); + } + // Flush all events x_sync(ps->c); ev_io_stop(ps->loop, &ps->xiow); diff --git a/src/compton.h b/src/compton.h index f55257a..2b445ab 100644 --- a/src/compton.h +++ b/src/compton.h @@ -13,6 +13,7 @@ #include #include "common.h" +#include "backend/backend.h" #include "win.h" #include "x.h" #include "c2.h" diff --git a/src/config.h b/src/config.h index aff9a0d..0f31c56 100644 --- a/src/config.h +++ b/src/config.h @@ -79,6 +79,8 @@ typedef struct options_t { bool monitor_repaint; bool print_diagnostics; // === General === + /// Use the experimental new backends? + bool experimental_backends; /// Path to write PID to. char *write_pid_path; /// The backend in use. @@ -270,13 +272,14 @@ parse_config_libconfig(options_t *, const char *config_file, bool *shadow_enable bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask); #endif -void set_default_winopts(options_t *, win_option_mask_t *, bool shadow_enable, bool fading_enable); +void set_default_winopts(options_t *, win_option_mask_t *, bool shadow_enable, + bool fading_enable); /// Parse a configuration file is that is enabled, also initialize the winopt_mask with /// default values /// Outputs and returns: /// same as parse_config_libconfig char *parse_config(options_t *, const char *config_file, bool *shadow_enable, - bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask); + bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask); /** * Parse a backend option argument. diff --git a/src/options.c b/src/options.c index b3d54ba..bfca5f5 100644 --- a/src/options.c +++ b/src/options.c @@ -440,6 +440,7 @@ static const struct option longopts[] = { {"log-file", required_argument, NULL, 322}, {"reredir-on-root-change", no_argument, NULL, 731}, {"glx-reinit-on-root-change", no_argument, NULL, 732}, + {"experimental-backends", no_argument, NULL, 733}, {"monitor-repaint", no_argument, NULL, 800}, {"diagnostics", no_argument, NULL, 801}, // Must terminate with a NULL entry @@ -770,6 +771,7 @@ void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable, P_CASEBOOL(319, no_x_selection); P_CASEBOOL(731, reredir_on_root_change); P_CASEBOOL(732, glx_reinit_on_root_change); + P_CASEBOOL(733, experimental_backends); P_CASEBOOL(800, monitor_repaint); case 801: opt->print_diagnostics = true; break; default: usage(1); break; diff --git a/src/win.c b/src/win.c index 03fe7f1..1944032 100644 --- a/src/win.c +++ b/src/win.c @@ -24,6 +24,7 @@ #include "log.h" #include "types.h" #include "region.h" +#include "backend/backend.h" #include "render.h" #ifdef CONFIG_DBUS @@ -609,7 +610,12 @@ void calc_win_size(session_t *ps, win *w) { calc_shadow_geometry(ps, w); w->flags |= WFLAG_SIZE_CHANGE; // Invalidate the shadow we built - free_paint(ps, &w->shadow_paint); + if (ps->o.experimental_backends) { + backend_list[ps->o.backend]->release_win(ps->backend_data, ps, w, w->win_data); + w->win_data = backend_list[ps->o.backend]->prepare_win(ps->backend_data, ps, w); + } else { + free_paint(ps, &w->shadow_paint); + } } /** @@ -1228,9 +1234,21 @@ void win_update_bounding_shape(session_t *ps, win *w) { win_rounded_corners(ps, w); // Window shape changed, we should free old wpaint and shadow pict - free_paint(ps, &w->paint); - free_paint(ps, &w->shadow_paint); - //log_trace("free out dated pict"); + if (ps->o.experimental_backends) { + //log_trace("free out dated pict"); + // Window shape changed, we should free win_data + if (ps->redirected && w->state == WSTATE_MAPPED) { + // Note we only do this when screen is redirected, because + // otherwise win_data is not valid + backend_info_t *bi = backend_list[ps->o.backend]; + bi->release_win(ps->backend_data, ps, w, w->win_data); + w->win_data = bi->prepare_win(ps->backend_data, ps, w); + //log_trace("free out dated pict"); + } + } else { + free_paint(ps, &w->paint); + free_paint(ps, &w->shadow_paint); + } win_on_factor_change(ps, w); } @@ -1321,8 +1339,17 @@ finish_unmap_win(session_t *ps, win **_w) { w->state = WSTATE_UNMAPPED; w->flags = 0; - free_paint(ps, &w->paint); - free_paint(ps, &w->shadow_paint); + if (ps->o.experimental_backends) { + // We are in unmap_win, we definitely was viewable + if (ps->redirected) { + assert(w->win_data); + backend_list[ps->o.backend]->release_win(ps->backend_data, ps, w, w->win_data); + w->win_data = NULL; + } + } else { + free_paint(ps, &w->paint); + free_paint(ps, &w->shadow_paint); + } } static void @@ -1347,7 +1374,9 @@ finish_destroy_win(session_t *ps, win **_w) { ps->active_win = NULL; } - free_win_res(ps, w); + if (!ps->o.experimental_backends) { + free_win_res(ps, w); + } // Drop w from all prev_trans to avoid accessing freed memory in // repair_win()