From 75912d23f3f81b696aededf29216a22e8e97470d Mon Sep 17 00:00:00 2001 From: Richard Grenville Date: Sat, 23 Mar 2013 22:06:41 +0800 Subject: [PATCH] Improvement: --blur-background-exclude #98 & MESA_swap_control & others - Add --blur-background-exclude. (#98) - Add `opengl-mswc` VSync, which uses MESA_swap_control instead of SGI_swap_control. I don't expect it to perform better than SGI_swap_control, though. - Update CMakeLists.txt . - Add a few targets for D-Bus `win_get`. Misc changes. - Known issue: Apparently I've forgotten implementing --inactive-dim on GLX backend... Silly me. --- _CMakeLists.txt | 27 +++++++++--- compton.sample.conf | 1 + man/compton.1.asciidoc | 3 +- src/common.h | 10 +++++ src/compton.c | 94 ++++++++++++++++++++++++++++++++++++------ src/compton.h | 9 ++++ src/dbus.c | 5 +++ 7 files changed, 131 insertions(+), 18 deletions(-) diff --git a/_CMakeLists.txt b/_CMakeLists.txt index 5a306dd..fe40f7e 100644 --- a/_CMakeLists.txt +++ b/_CMakeLists.txt @@ -8,14 +8,19 @@ set(CPACK_PACKAGE_VERSION_PATCH "0") add_subdirectory(man) set(compton_SRCS src/compton.c) -add_executable(compton ${compton_SRCS}) set(CMAKE_C_FLAGS_DEBUG "-ggdb") set(CMAKE_C_FLAGS_RELEASE "-O2 -march=native") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -march=native -ggdb") +set(CMAKE_C_FLAGS_RELWITHDBGINFO "-O2 -march=native -ggdb") add_definitions("-Wall" "-std=c99") +# == Version == +execute_process(COMMAND sh -c "echo -n \\\"git-$(git describe --always --dirty)-$(git log -1 --date=short --pretty=format:%cd)\\\"" + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE COMPTON_VERSION) +add_definitions("-DCOMPTON_VERSION=${COMPTON_VERSION}") + # == Options == option(CONFIG_REGEX_PCRE "Enable PCRE regular expression support for blacklist entries (requires libpcre)" ON) @@ -38,11 +43,20 @@ if (CONFIG_VSYNC_DRM) add_definitions("-DCONFIG_VSYNC_DRM") endif () -option(CONFIG_VSYNC_OPENGL "Enable OpenGL VSync support" ON) +option(CONFIG_VSYNC_OPENGL "Enable OpenGL support" ON) if (CONFIG_VSYNC_OPENGL) add_definitions("-DCONFIG_VSYNC_OPENGL") + list(APPEND compton_SRCS src/opengl.c) endif () +option(CONFIG_C2 "Enable matching system" ON) +if (CONFIG_C2) + add_definitions("-DCONFIG_C2") + list(APPEND compton_SRCS src/c2.c) +endif () + +add_executable(compton ${compton_SRCS}) + # == Find libraries == target_link_libraries(compton "-lm" "-lrt") @@ -74,12 +88,14 @@ X11LIB_CHK(Xrandr) # --- Find libpcre --- if (CONFIG_REGEX_PCRE) pkg_check_modules(LIBPCRE REQUIRED libpcre>=8.12) + add_definitions("${LIBPCRE_CFLAGS}") target_link_libraries(compton "${LIBPCRE_LDFLAGS}") endif () # --- Find libconfig --- if (CONFIG_LIBCONFIG) pkg_check_modules(LIBCONFIG REQUIRED libconfig>=1.3.2) + add_definitions("${LIBCONFIG_CFLAGS}") target_link_libraries(compton "${LIBCONFIG_LDFLAGS}") if (LIBCONFIG_VERSION VERSION_LESS 1.4) add_definitions("-DCONFIG_LIBCONFIG_LEGACY") @@ -91,6 +107,7 @@ endif () if (CONFIG_VSYNC_DRM) pkg_check_modules(LIBDRM REQUIRED libdrm) # We only use its header file + add_definitions("${LIBDRM_CFLAGS}") endif () # == Install == @@ -121,8 +138,8 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/desc.txt") set(CPACK_GENERATOR "TBZ2" "DEB" "RPM") set(CPACK_MONOLITHIC_INSTALL 1) set(CPACK_STRIP_FILES 1) -set(CPACK_RESOURCE_FILE_LICENSE "LICENSE") -set(CPACK_RESOURCE_FILE_README "README.md") +set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") +set(CPACK_RESOURCE_FILE_README "${PROJECT_SOURCE_DIR}/README.md") # --- Source package config --- set(CPACK_SOURCE_GENERATOR "TBZ2" "DEB" "RPM") diff --git a/compton.sample.conf b/compton.sample.conf index a5fc78d..5be5e71 100644 --- a/compton.sample.conf +++ b/compton.sample.conf @@ -25,6 +25,7 @@ alpha-step = 0.06; # blur-background = true; # blur-background-frame = true; blur-background-fixed = false; +blur-background-exclude = [ "window_type = 'dock'", "window_type = 'desktop'" ]; # Fading fading = true; diff --git a/man/compton.1.asciidoc b/man/compton.1.asciidoc index 6248180..fc64cc1 100644 --- a/man/compton.1.asciidoc +++ b/man/compton.1.asciidoc @@ -120,7 +120,7 @@ OPTIONS Specify refresh rate of the screen. If not specified or 0, compton will try detecting this with X RandR extension. *--vsync* 'VSYNC_METHOD':: - Set VSync method. There are 3 VSync methods currently available: + Set VSync method. VSync methods currently available: + -- * 'none': No VSync @@ -128,6 +128,7 @@ OPTIONS * 'opengl': Try to VSync with 'SGI_swap_control' OpenGL extension. Only work on some drivers. Experimental. * 'opengl-oml': Try to VSync with 'OML_sync_control' OpenGL extension. Only work on some drivers. Experimental. * 'opengl-swc': Try to VSync with 'SGI_swap_control' OpenGL extension. Only work on some drivers. Works only with GLX backend. Known to be most effective on many drivers. Does not actually control paint timing, only buffer swap is affected, so it doesn't have the effect of *--sw-opti* unlike other methods. Experimental. +* 'opengl-mswc': Try to VSync with 'MESA_swap_control' OpenGL extension. Basically the same as 'opengl-swc' above, except the extension we use. (Note some VSync methods may not be enabled at compile time.) -- diff --git a/src/common.h b/src/common.h index 2f8b6e2..249ef92 100644 --- a/src/common.h +++ b/src/common.h @@ -260,6 +260,7 @@ typedef enum { VSYNC_OPENGL, VSYNC_OPENGL_OML, VSYNC_OPENGL_SWC, + VSYNC_OPENGL_MSWC, NUM_VSYNC, } vsync_t; @@ -280,6 +281,7 @@ typedef Bool (*f_GetSyncValuesOML) (Display* dpy, GLXDrawable drawable, int64_t* typedef Bool (*f_WaitForMscOML) (Display* dpy, GLXDrawable drawable, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t* ust, int64_t* msc, int64_t* sbc); typedef int (*f_SwapIntervalSGI) (int interval); +typedef int (*f_SwapIntervalMESA) (unsigned int interval); typedef void (*f_BindTexImageEXT) (Display *display, GLXDrawable drawable, int buffer, const int *attrib_list); typedef void (*f_ReleaseTexImageEXT) (Display *display, GLXDrawable drawable, int buffer); @@ -443,6 +445,8 @@ typedef struct { /// Whether to use fixed blur strength instead of adjusting according /// to window opacity. bool blur_background_fixed; + /// Background blur blacklist. A linked list of conditions. + c2_lptr_t *blur_background_blacklist; /// How much to dim an inactive window. 0.0 - 1.0, 0 to disable. double inactive_dim; /// Whether to use fixed inactive dim opacity, instead of deciding @@ -624,6 +628,8 @@ typedef struct { f_WaitForMscOML glXWaitForMscOML; /// Pointer to glXSwapIntervalSGI function. f_SwapIntervalSGI glXSwapIntervalProc; + /// Pointer to glXSwapIntervalMESA function. + f_SwapIntervalMESA glXSwapIntervalMESAProc; /// Pointer to glXBindTexImageEXT function. f_BindTexImageEXT glXBindTexImageProc; /// Pointer to glXReleaseTexImageEXT function. @@ -821,6 +827,7 @@ typedef struct _win { const c2_lptr_t *cache_fblst; const c2_lptr_t *cache_fcblst; const c2_lptr_t *cache_ivclst; + const c2_lptr_t *cache_bbblst; // Opacity-related members /// Current window opacity. @@ -880,6 +887,9 @@ typedef struct _win { /// Override value of window color inversion state. Set by D-Bus method /// calls. switch_t invert_color_force; + + /// Whether to blur window background. + bool blur_background; } win; /// Temporary structure used for communication between diff --git a/src/compton.c b/src/compton.c index f37746a..ccdd23d 100644 --- a/src/compton.c +++ b/src/compton.c @@ -33,11 +33,12 @@ const char * const WINTYPES[NUM_WINTYPES] = { /// Names of VSync modes. const char * const VSYNC_STRS[NUM_VSYNC] = { - "none", // VSYNC_NONE - "drm", // VSYNC_DRM - "opengl", // VSYNC_OPENGL - "opengl-oml", // VSYNC_OPENGL_OML - "opengl-swc", // VSYNC_OPENGL_SWC + "none", // VSYNC_NONE + "drm", // VSYNC_DRM + "opengl", // VSYNC_OPENGL + "opengl-oml", // VSYNC_OPENGL_OML + "opengl-swc", // VSYNC_OPENGL_SWC + "opengl-mswc", // VSYNC_OPENGL_MSWC }; /// Names of backends. @@ -48,10 +49,11 @@ const char * const BACKEND_STRS[NUM_BKEND] = { /// Function pointers to init VSync modes. static bool (* const (VSYNC_FUNCS_INIT[NUM_VSYNC]))(session_t *ps) = { - [VSYNC_DRM ] = vsync_drm_init, - [VSYNC_OPENGL ] = vsync_opengl_init, - [VSYNC_OPENGL_OML ] = vsync_opengl_oml_init, - [VSYNC_OPENGL_SWC ] = vsync_opengl_swc_init, + [VSYNC_DRM ] = vsync_drm_init, + [VSYNC_OPENGL ] = vsync_opengl_init, + [VSYNC_OPENGL_OML ] = vsync_opengl_oml_init, + [VSYNC_OPENGL_SWC ] = vsync_opengl_swc_init, + [VSYNC_OPENGL_MSWC ] = vsync_opengl_mswc_init, }; /// Function pointers to wait for VSync. @@ -1560,7 +1562,8 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint) { free_picture(ps, &pict); // Dimming the window if needed - if (w->dim && w->dim_alpha_pict != ps->alpha_picts[0]) { + if (BKEND_XRENDER == ps->o.backend + && w->dim && w->dim_alpha_pict != ps->alpha_picts[0]) { XRenderComposite(ps->dpy, PictOpOver, ps->black_picture, w->dim_alpha_pict, ps->tgt_buffer, 0, 0, 0, 0, x, y, wid, hei); } @@ -1725,8 +1728,8 @@ paint_all(session_t *ps, XserverRegion region, win *t) { if (!is_region_empty(ps, reg_paint)) { set_tgt_clip(ps, reg_paint); // Blur window background - if ((ps->o.blur_background && WMODE_SOLID != w->mode) - || (ps->o.blur_background_frame && w->frame_opacity)) { + if (w->blur_background && (WMODE_SOLID != w->mode + || (ps->o.blur_background_frame && w->frame_opacity))) { win_blur_background(ps, w, ps->tgt_buffer, reg_paint); } @@ -1977,6 +1980,8 @@ map_win(session_t *ps, Window id) { } win_determine_fade(ps, w); + win_determine_blur_background(ps, w); + w->damaged = false; /* if any configure events happened while @@ -2292,6 +2297,23 @@ win_determine_invert_color(session_t *ps, win *w) { add_damage_win(ps, w); } +/** + * Determine if a window should have background blurred. + */ +static void +win_determine_blur_background(session_t *ps, win *w) { + bool blur_background_old = w->blur_background; + + w->blur_background = ps->o.blur_background + && !win_match(ps, w, ps->o.blur_background_blacklist, &w->cache_bbblst); + + // Only consider window damaged if it's previously painted with background + // blurred + if (w->blur_background != blur_background_old && (WMODE_SOLID != w->mode + || (ps->o.blur_background_frame && w->frame_opacity))) + add_damage_win(ps, w); +} + /** * Function to be called on window type changes. */ @@ -2317,6 +2339,8 @@ win_on_factor_change(session_t *ps, win *w) { win_determine_invert_color(ps, w); if (ps->o.focus_blacklist) win_update_focused(ps, w); + if (ps->o.blur_background_blacklist) + win_determine_blur_background(ps, w); } /** @@ -2533,6 +2557,7 @@ add_win(session_t *ps, Window id, Window prev) { .cache_fblst = NULL, .cache_fcblst = NULL, .cache_ivclst = NULL, + .cache_bbblst = NULL, .opacity = 0, .opacity_tgt = 0, @@ -2563,6 +2588,8 @@ add_win(session_t *ps, Window id, Window prev) { .invert_color = false, .invert_color_force = UNSET, + + .blur_background = false, }; // Reject overlay window and already added windows @@ -4097,6 +4124,9 @@ usage(void) { " Does not actually control paint timing, only buffer swap is\n" " affected, so it doesn't have the effect of --sw-opti unlike\n" " other methods. Experimental." WARNING "\n" + " opengl-mswc = Try to VSync with MESA_swap_control OpenGL\n" + " extension. Basically the same as opengl-swc above, except the\n" + " extension we use." WARNING "\n" "--alpha-step val\n" " Step for pregenerating alpha pictures. 0.01 - 1.0. Defaults to\n" " 0.03.\n" @@ -4549,6 +4579,8 @@ parse_config(session_t *ps, struct options_tmp *pcfgtmp) { parse_cfg_condlst(ps, &cfg, &ps->o.focus_blacklist, "focus-exclude"); // --invert-color-include parse_cfg_condlst(ps, &cfg, &ps->o.invert_color_list, "invert-color-include"); + // --blur-background-exclude + parse_cfg_condlst(ps, &cfg, &ps->o.blur_background_blacklist, "blur-background-exclude"); // --blur-background lcfg_lookup_bool(&cfg, "blur-background", &ps->o.blur_background); // --blur-background-frame @@ -4630,6 +4662,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { { "benchmark", required_argument, NULL, 293 }, { "benchmark-wid", required_argument, NULL, 294 }, { "glx-use-copysubbuffermesa", no_argument, NULL, 295 }, + { "blur-background-exclude", required_argument, NULL, 296 }, // Must terminate with a NULL entry { NULL, 0, NULL, 0 }, }; @@ -4912,6 +4945,10 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { // --glx-use-copysubbuffermesa ps->o.glx_use_copysubbuffermesa = true; break; + case 296: + // --blur-background-exclude + condlst_add(ps, &ps->o.blur_background_blacklist, optarg); + break; default: usage(); break; @@ -4955,6 +4992,10 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { if (ps->o.blur_background_frame) ps->o.blur_background = true; + // Free background blur blacklist if background blur is not actually enabled + if (!ps->o.blur_background) + free_wincondlst(&ps->o.blur_background_blacklist); + // Other variables determined by options // Determine whether we need to track focus changes @@ -5238,6 +5279,34 @@ vsync_opengl_swc_init(session_t *ps) { #endif } +static bool +vsync_opengl_mswc_init(session_t *ps) { +#ifdef CONFIG_VSYNC_OPENGL + if (!ensure_glx_context(ps)) + return false; + + if (BKEND_GLX != ps->o.backend) { + printf_errf("(): I'm afraid glXSwapIntervalMESA wouldn't help if you are " + "not using GLX backend. You could try, nonetheless."); + } + + // Get video sync functions + if (!ps->glXSwapIntervalMESAProc) + ps->glXSwapIntervalMESAProc = (f_SwapIntervalMESA) + glXGetProcAddress ((const GLubyte *) "glXSwapIntervalMESA"); + if (!ps->glXSwapIntervalMESAProc) { + printf_errf("(): Failed to get MESA_swap_control function."); + return false; + } + ps->glXSwapIntervalMESAProc(1); + + return true; +#else + printf_errf("(): Program not compiled with OpenGL VSync support."); + return false; +#endif +} + #ifdef CONFIG_VSYNC_OPENGL /** * Wait for next VSync, OpenGL method. @@ -5759,6 +5828,7 @@ session_init(session_t *ps_old, int argc, char **argv) { .blur_background = false, .blur_background_frame = false, .blur_background_fixed = false, + .blur_background_blacklist = NULL, .inactive_dim = 0.0, .inactive_dim_fixed = false, .invert_color_list = NULL, diff --git a/src/compton.h b/src/compton.h index b590b0e..77d3b6b 100644 --- a/src/compton.h +++ b/src/compton.h @@ -667,6 +667,12 @@ win_update_prop_shadow(session_t *ps, win *w); static void win_determine_shadow(session_t *ps, win *w); +static void +win_determine_invert_color(session_t *ps, win *w); + +static void +win_determine_blur_background(session_t *ps, win *w); + static void win_on_wtype_change(session_t *ps, win *w); @@ -988,6 +994,9 @@ vsync_opengl_oml_init(session_t *ps); static bool vsync_opengl_swc_init(session_t *ps); +static bool +vsync_opengl_mswc_init(session_t *ps); + #ifdef CONFIG_VSYNC_OPENGL static int vsync_opengl_wait(session_t *ps); diff --git a/src/dbus.c b/src/dbus.c index 25b37fd..48f847c 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -716,6 +716,11 @@ cdbus_process_win_get(session_t *ps, DBusMessage *msg) { cdbus_m_win_get_do(right_width, cdbus_reply_uint32); cdbus_m_win_get_do(top_width, cdbus_reply_uint32); cdbus_m_win_get_do(bottom_width, cdbus_reply_uint32); + + cdbus_m_win_get_do(shadow, cdbus_reply_bool); + cdbus_m_win_get_do(fade, cdbus_reply_bool); + cdbus_m_win_get_do(invert_color, cdbus_reply_bool); + cdbus_m_win_get_do(blur_background, cdbus_reply_bool); #undef cdbus_m_win_get_do printf_errf("(): " CDBUS_ERROR_BADTGT_S, target);