Closed dflock closed 11 years ago
This feature would also be useful for excluding video players out of the unredirect list (in order to keep vsync active and eliminate tearing).
The feature is in richardgv-dev
branch, and it should be rather intuitive to use, I guess. See the commit log above and compton -h
. I hope there aren't any big issues. Sorry for the long delay, I don't have as much time to invest since I got a job.
In addition to --unredir-if-possible-exclude
, --unredir-if-possible-delay
may be helpful for flickering of high frequency.
And, the problem probably isn't that simple. Flickering when (un)redirecting screen is normal, but corruptions and freezes may be hints of bugs in compton or your driver. You may wish to further investigate the issue by, for example, debugging compton with gdb when it's freezing.
Also, you may use the D-Bus interface to (un)redirect screen (see dbus-examples/cdbus-driver.sh
) for more fine-grained control.
@dflock:
Your blog entry is one of the most extensive introduction to compton I've seen. :-) And the illustration in your other posts are interesting.
We typically recommend against matching with window name, because, huh, you could very well have a Firefox window with "Chrome" in its name when you are visiting a web page with such title.
glx-no-rebind-pixmap
is a pretty safe optimization. It's only known to break on LLVMpipe.
glx-swap-method
should be helpful on older cards. Although nvidia-driver supports GLX_EXT_buffer_age
, it seemingly doesn't return the correct value, and I typically use 3
. (Note if you use both --blur-background
and --glx-swap-method
, --resize-damage
may be needed to eliminate some artifacts.)
--unredir-if-possible-exclude
works great for me so far. I have yet to encounter any issues. Looking forward to seeing this added as a config option.
I don't know if this is the right place to ask but I have a somewhat related problem:
I am sometimes running a graphically intensive 3D application on one screen while having a regular desktop and windows render on the other. From my experience 3D rendering does take quite a significant hit when compositing is enabled. That's why I am wondering if unredirecting the content on one screen - if technically feasible - could maybe alleviate that.
To take things further, would it be possible to disable compositing for single applications? And if so, could this increase the performance when working with this particular application or does composition have to be disabled altogether to see any performance gains?
I don't know too much about the linux graphic stack and/or compositing so please excuse me if these ideas are completely stupid or out of touch with reality :). I would love to hear your thoughts, though.
Thanks, again, for taking the time to read this.
--unredir-if-possible-exclude
works great for me so far. I have yet to encounter any issues. Looking forward to seeing this added as a config option.
Could you please test if --unredir-if-possible-delay
works as well? I wish to add both to configuration file at once.
I am sometimes running a graphically intensive 3D application on one screen while having a regular desktop and windows render on the other. From my experience 3D rendering does take quite a significant hit when compositing is enabled. That's why I am wondering if unredirecting the content on one screen - if technically feasible - could maybe alleviate that.
If you have several separate X screens, then yes, just avoid running compton on the screen you don't wish to redirect; if you use Xinerama/TwinView that combines your screens to one big virtual screen, then no, I'm not aware of a way to redirect a specific region on the screen. For redirecting a specific window, see below.
To take things further, would it be possible to disable compositing for single applications? And if so, could this increase the performance when working with this particular application or does composition have to be disabled altogether to see any performance gains?
Although technically possible, I suppose it actually breaks window stacking. I don't think you could have a unredirected window sitting below any redirected windows correctly. Remember how X composite works: It lets a client composite pictures of redirected windows to the final composited screen image with all the fancy effects, and paints it to the root window. How could X then correctly stack one unredirected window into this image if the unredirected window is not on the top of all redirected windows?
And even if it works, removing a single window probably isn't going to bring massive performance improvement anyway.
I would say if you have used some painting-rate throttling options (--vsync=drm/opengl/opengl-oml
, --sw-opti
), and your CPU/GPU is not fully occupied, compton shouldn't bring too much impact on performance.
Perhaps, the source of a large part of the performance loss is not in compton but somewhere else -- X composite, maybe. With a full-screen glxgears, a properly optimized compton (without using VSync, aka --opengl --glx-swap-method 3 --glx-no-stencil --glx-no-rebind-pixmap
) only introduces about 3% performance loss (FPS 6000 vs. 5800), but when there are lots of windows, the performance loss is around 25% here (FPS 33000 vs. 25000), even when I limit painting rate to 60Hz, and disabling painting of all windows with --paint-exclude
. Wayland is probably the solution.
Some articles about compositor performance I found. People say compositing is not going to bring performance loss, and god knows how it happened.
http://blog.martin-graesslin.com/blog/2013/05/compositing-and-lightweight-desktops/ http://blog.fishsoup.net/2011/06/13/benchmarking-compositor-performance/ http://www.phoronix.com/scan.php?page=article&item=linux_desktop_managers1&num=1 http://www.phoronix.com/scan.php?page=article&item=ubuntu_unity_64&num=1
Richard, thank you for your very detailed response. Both your remarks and the links were very interesting to read and I can now safely say that I understand the performance impact of compositing much better than before.
Most of my particular issues with graphics performance probably stem from FGLRX. And believe me, as soon as Linux 3.12 and the new Mesa drivers become more stable I'll say farewell to proprietary AMD drivers.
Could you please test if --unredir-if-possible-delay works as well? I wish to add both to configuration file at once.
I have done some testing with this option active and found a few problems:
Here's a recording of top
and compton
's output while setting a newly spawned window to fullscreen:
compton --config '/home/bob/.config/compton/compton.conf' --unredir-if-possible-delay 3
restack_win(0x0100f6de, 0x0100f670): Failed to found new above window.
[ 112.80 ] error 3 (BadWindow) request 2 minor 0 serial 1658413 ("BadWindow (invalid Window parameter)")
[ 130.91 ] error 3 (BadWindow) request 20 minor 0 serial 1676397 ("BadWindow (invalid Window parameter)")
[ 130.91 ] error 3 (BadWindow) request 20 minor 0 serial 1676398 ("BadWindow (invalid Window parameter)")
[ 130.91 ] error 3 (BadWindow) request 20 minor 0 serial 1676399 ("BadWindow (invalid Window parameter)")
[ 130.91 ] error 3 (BadWindow) request 20 minor 0 serial 1676400 ("BadWindow (invalid Window parameter)")
# Recording start
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2737 root 20 0 484m 224m 196m S 2 5.9 11:59.08 Xorg
16106 bob 20 0 108m 29m 18m S 0 0.8 0:34.42 compton
# Window in fullscreen
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16106 bob 20 0 108m 29m 18m R 23 0.8 0:35.55 compton
2737 root 20 0 520m 245m 218m S 16 6.4 11:59.86 Xorg
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16106 bob 20 0 108m 29m 18m R 98 0.8 0:40.47 compton
2737 root 20 0 512m 237m 210m S 3 6.2 12:00.03 Xorg
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16106 bob 20 0 108m 29m 18m R 97 0.8 0:45.31 compton
2737 root 20 0 519m 245m 218m S 12 6.4 12:00.61 Xorg
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16106 bob 20 0 108m 29m 18m R 96 0.8 0:50.13 compton
2737 root 20 0 520m 245m 218m S 9 6.4 12:01.06 Xorg
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16106 bob 20 0 108m 29m 18m R 95 0.8 0:54.86 compton
2737 root 20 0 520m 245m 218m R 16 6.4 12:01.85 Xorg
# Window restored
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16106 bob 20 0 108m 29m 18m S 18 0.8 1:26.57 compton
2737 root 20 0 493m 232m 205m R 11 6.1 12:12.07 Xorg
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2737 root 20 0 528m 250m 222m S 16 6.6 12:12.89 Xorg
16106 bob 20 0 108m 29m 18m S 2 0.8 1:26.65 compton
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2737 root 20 0 519m 241m 214m S 4 6.3 12:13.08 Xorg
16106 bob 20 0 108m 29m 18m S 0 0.8 1:26.67 compton
@Feltzer:
Modify some primary sections to attempt to resolve the issues, but it may bring other problems. I'm at work, can't test much:
diff --git a/src/compton.c b/src/compton.c
index b8f1fc6..77b44b6 100644
--- a/src/compton.c
+++ b/src/compton.c
@@ -1102,9 +1102,16 @@ paint_preprocess(session_t *ps, win *list) {
next = w->next;
opacity_t opacity_old = w->opacity;
- // Destroy reg_ignore on all windows if they should expire
- if (ps->reg_ignore_expire)
- free_region(ps, &w->reg_ignore);
+ // Data expiration
+ {
+ // Remove built shadow if needed
+ if (w->flags & WFLAG_SIZE_CHANGE)
+ free_paint(ps, &w->shadow_paint);
+
+ // Destroy reg_ignore on all windows if they should expire
+ if (ps->reg_ignore_expire)
+ free_region(ps, &w->reg_ignore);
+ }
// Update window opacity target and dim state if asked
if (WFLAG_OPCT_CHANGE & w->flags) {
@@ -1115,43 +1122,33 @@ paint_preprocess(session_t *ps, win *list) {
// Run fading
run_fade(ps, w, steps);
+ // Opacity will not change, for now on.
+
// Give up if it's not damaged or invisible, or it's unmapped and its
- // pixmap is gone (for example due to a ConfigureNotify)
+ // pixmap is gone (for example due to a ConfigureNotify), or when it's
+ // excluded
if (!w->damaged
|| w->a.x + w->a.width < 1 || w->a.y + w->a.height < 1
|| w->a.x >= ps->root_width || w->a.y >= ps->root_height
- || ((IsUnmapped == w->a.map_state || w->destroyed)
- && !w->paint.pixmap)) {
+ || ((IsUnmapped == w->a.map_state || w->destroyed) && !w->paint.pixmap)
+ || get_alpha_pict_o(ps, w->opacity) == ps->alpha_picts[0]
+ || w->paint_excluded)
to_paint = false;
- }
- to_paint = to_paint && !w->paint_excluded;
+ // to_paint will never change afterward
- if (to_paint) {
- // If opacity changes
- if (w->opacity != opacity_old) {
- win_determine_mode(ps, w);
- add_damage_win(ps, w);
- }
-
- if (get_alpha_pict_o(ps, w->opacity) == ps->alpha_picts[0])
- to_paint = false;
- }
+ // Determine mode as early as possible
+ if ((to_paint && !w->to_paint) || w->opacity != opacity_old)
+ win_determine_mode(ps, w);
if (to_paint) {
// Fetch bounding region
- if (!w->border_size) {
+ if (!w->border_size)
w->border_size = border_size(ps, w, true);
- }
// Fetch window extents
- if (!w->extents) {
+ if (!w->extents)
w->extents = win_extents(ps, w);
- // If w->extents does not exist, the previous add_damage_win()
- // call when opacity changes has no effect, so redo it here.
- if (w->opacity != opacity_old)
- add_damage_win(ps, w);
- }
// Calculate frame_opacity
{
@@ -1164,6 +1161,8 @@ paint_preprocess(session_t *ps, win *list) {
else
w->frame_opacity = 0.0;
+ // Destroy all reg_ignore above when frame opacity changes on
+ // SOLID mode
if (w->to_paint && WMODE_SOLID == mode_old
&& (0.0 == frame_opacity_old) != (0.0 == w->frame_opacity))
ps->reg_ignore_expire = true;
@@ -1174,24 +1173,18 @@ paint_preprocess(session_t *ps, win *list) {
w->shadow_opacity = ps->o.shadow_opacity * w->frame_opacity;
else
w->shadow_opacity = ps->o.shadow_opacity * get_opacity_percent(w);
-
- // Rebuild shadow if necessary
- if (w->flags & WFLAG_SIZE_CHANGE) {
- free_paint(ps, &w->shadow_paint);
- }
-
- if (w->shadow && !paint_isvalid(ps, &w->shadow_paint))
- win_build_shadow(ps, w, 1);
}
+ // Add window to damaged area if its painting status changes
+ // or opacity changes
+ if (to_paint != w->to_paint || w->opacity != opacity_old)
+ add_damage_win(ps, w);
+
+ // Destroy all reg_ignore above when window mode changes
if ((to_paint && WMODE_SOLID == w->mode)
!= (w->to_paint && WMODE_SOLID == mode_old))
ps->reg_ignore_expire = true;
- // Add window to damaged area if its painting status changes
- if (to_paint != w->to_paint)
- add_damage_win(ps, w);
-
if (to_paint) {
// Generate ignore region for painting to reduce GPU load
if (ps->reg_ignore_expire || !w->to_paint) {
@@ -1264,6 +1257,10 @@ paint_preprocess(session_t *ps, win *list) {
if (UNSET != ps->o.redirected_force)
unredir_possible = !ps->o.redirected_force;
+ // If there's no window to paint, and the screen isn't redirected,
+ // don't redirect it.
+ if (ps->o.unredir_if_possible && is_highest && !ps->redirected)
+ unredir_possible = true;
if (unredir_possible) {
if (ps->redirected) {
if (!ps->o.unredir_if_possible_delay || ps->tmout_unredir_hit)
@@ -1785,6 +1782,10 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
for (win *w = t; w; w = w->prev_trans) {
// Painting shadow
if (w->shadow) {
+ // Lazy shadow building
+ if (!paint_isvalid(ps, &w->shadow_paint))
+ win_build_shadow(ps, w, 1);
+
// Shadow is to be painted based on the ignore region of current
// window
if (w->reg_ignore) {
@@ -2050,6 +2051,13 @@ wid_get_prop_wintype(session_t *ps, Window wid) {
static void
map_win(session_t *ps, Window id) {
+ // Unmap overlay window if it got mapped but we are currently not
+ // in redirected state.
+ if (ps->overlay && id == ps->overlay && !ps->redirected) {
+ XUnmapWindow(ps->dpy, ps->overlay);
+ XFlush(ps->dpy);
+ }
+
win *w = find_win(ps, id);
// Don't care about window mapping if it's an InputOnly window
@@ -2831,14 +2839,13 @@ add_win(session_t *ps, Window id, Window prev) {
assert(IsViewable == map_state || IsUnmapped == map_state);
new->a.map_state = IsUnmapped;
- // Get window picture format
- if (InputOutput == new->a.class)
+ if (InputOutput == new->a.class) {
+ // Get window picture format
new->pictfmt = XRenderFindVisualFormat(ps->dpy, new->a.visual);
- // Create Damage for window
- if (InputOutput == new->a.class) {
- set_ignore_next(ps);
- new->damage = XDamageCreate(ps->dpy, id, XDamageReportNonEmpty);
+ // Create Damage for window
+ set_ignore_next(ps);
+ new->damage = XDamageCreate(ps->dpy, id, XDamageReportNonEmpty);
}
calc_win_size(ps, new);
@@ -6097,6 +6104,11 @@ init_overlay(session_t *ps) {
// Retrieve DamageNotify on root window if we are painting on an
// overlay
// root_damage = XDamageCreate(ps->dpy, root, XDamageReportNonEmpty);
+
+ // Unmap overlay, firstly. But this typically does not work because
+ // the window isn't created yet.
+ // XUnmapWindow(ps->dpy, ps->overlay);
+ // XFlush(ps->dpy);
}
else {
fprintf(stderr, "Cannot get X Composite overlay window. Falling "
@@ -6371,6 +6383,9 @@ tmout_unredir_callback(session_t *ps, timeout_t *tmout) {
*/
static bool
mainloop(session_t *ps) {
+ // Don't miss timeouts even when we have a LOT of other events!
+ timeout_run(ps);
+
// Process existing events
// Sometimes poll() returns 1 but no events are actually read,
// causing XNextEvent() to block, I have no idea what's wrong, so we
@@ -6444,8 +6459,6 @@ mainloop(session_t *ps) {
free(ptv);
ptv = NULL;
- timeout_run(ps);
-
return true;
}
@@ -6732,6 +6745,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
| ExposureMask
| StructureNotifyMask
| PropertyChangeMask);
+ XFlush(ps->dpy);
ps->root_width = DisplayWidth(ps->dpy, ps->scr);
ps->root_height = DisplayHeight(ps->dpy, ps->scr);
Updated patch: https://gist.github.com/richardgv/6524881
The reason I don't merge it is I found a very strange bug after applying the patch: With GTX 670 and x11-drivers/nvidia-drivers-325.15, and compton --unredir-if-possible --config /dev/null
, if you send a SIGUSR1
to compton when a full-screen solid window is there, in which case compton either redirects then immediately unredirects the screen, or just don't redirect it altogether, X freezes after compton unredirects the screen. Requests sent by other X clients are not responded until compton is killed, which indicates the possibility of a bug in X. Attaching to X process shows X is on ./os/waitFor.c
. Backend does not matter. --paint-on-overlay
fixes the issue somehow. compton-git-v0.1_beta1-5-g4600f43-2013-08-28
doesn't exhibit the issue, but it's probably timing-related.
@Feltzer:
Changed pushed to richardgv-dev
branch despite the problem, since it's very rare and probably is a X bug. Does it solve your problems?
@richardgv:
Everything working fine here! Delay is correctly applied to both new and old windows and the performance issues are gone. Once again: Good work and thanks for the quick fix!
@richardgv
Hey Richard,
I just wanted to drop in quickly to ask if you are still planning to add these options to the config file. I'd love to be able to use the unredir exclude option this way.
Thanks in advance!
@Feltzer:
Ooooops, sorry, I forgot about it! Just added it as f202223 (richardgv-dev
branch).
Thanks for adding this, @richardgv. Unfortunately I can't seem to be able to get this to work again. Neither compton --unredir-if-possible --unredir-if-possible-exclude 'class_g = "vlc"'
nor
unredir-if-possible = true;
unredir-if-possible-exclude = [
"class_g ?= 'vlc'"
];
in the config file will work for me.
Can you confirm this or am I doing something wrong?
@Feltzer:
Well, I put the very content at the end of compton.sample.conf
, and it works here: Full-screen qvlc-2.0.7 no longer get unredirected, including "Full-screen interface" (F11) and full-screen video playback (after the control bar disappears). I dropped unredir-if-possible-exclude
and unredirection works correctly, as well.
The commandline argument --unredir-if-possible-exclude 'class_g = "vlc"'
will not work, because the general WM_CLASS
of a qvlc window (not sure about the themed vlc one) is "Vlc", not "vlc".
I would say most likely you made some tiny mistakes here: Wrote the content to the wrong file, case mistakes, forgot to build compton after git pull
, etc. Building compton with CPPFLAGS='-DDEBUG_REDIR -DDEBUG_C2'
might show you something helpful.
It would work the same way as
fade-exclude
but allow you to specify a list of window conditions that, when matched, would mean thatunredir-if-possible
is ignored. Something like:and used like:
The problem I'm having is that I have two monitors, and tend to have a code editor (sublimetext) open full-screen on the right monitor and other stuff non-fullscreen on the left one.
When I switch from one virtual workspace to another, to or from one with a full screen sublimetext, I tend to get flickering and corruption and sometimes freezes - especially if I flick rapidly between workspaces.
I think this is largely because of me having
unredir-if-possible
set, for full screen games performance. My full config is here: http://duncanlock.net/blog/2013/06/07/how-to-switch-to-compton-for-beautiful-tear-free-compositing-in-xfce/If there's a better way to fix this problem, or this feature wouldn't work, then I'd love to know :)
Thanks for all your work on Compton - much appreciated!