VSync #7

Open
ghost opened this Issue Feb 25, 2012 · 115 comments

Projects

None yet
@ghost
ghost commented Feb 25, 2012

Is it possible to implement vsync into compton? I like this compositor very much, but tearing is annoying some time.

@chjj
Owner
chjj commented Feb 27, 2012

I don't think there is any xrender function to explicitly get or wait for the vblank interval. It doesn't have any vsync support. I know the XFCE guys had a problem with this for their compositor. I also think compiz (GL) had a hard time maintaining a vsync feature because it would conflict with video drivers that were also trying to sync to the vblank rate. So even if I could, I would be hesitant about adding this.

@chjj chjj closed this Feb 27, 2012
@corenominal

Apologies for commenting on a closed issue, but I noticed that an initial tearing/vsync fix has been commited to cairo-compmgr. I have tested the fix and it seems to work well -- when watching http://www.youtube.com/watch?v=ZCPkOpMHB7g there is no visible tearing at all.

The commit, in case you wanted to check it out: http://git.tuxfamily.org/?p=ccm/cairocompmgr.git;a=commitdiff;h=efa4ceb97da501e8630ca7f12c99b1dce853c73e

I am loving compton and think it would be fantastic if this could be implemented as an option.

@glesik
glesik commented Jul 9, 2012

Sorry for yet another comment on closed issue, but I've found a patch which seems to implement vsync in Xfwm and thus, hopefully, enables tearing-free video playback:

https://bugzilla.xfce.org/show_bug.cgi?id=8898

I wonder if this or previously mentioned piece of code can be incorporated in Compton.

@Janhouse
Janhouse commented Oct 1, 2012

Compton with video tearing is kind of unusable.
I hope this gets fixed at some point.

@richardgv richardgv reopened this Oct 2, 2012
@richardgv
Collaborator
  1. As chjj pointed out, Xrender itself has no support for VSync. People says the whole X server isn't actually aware of VSync, only the driver is.
  2. Despite that I know nothing about OpenGL and little about X, I've thought about 3 approaches after some research:
    1. Pure software method. Detect the refresh rate with Xrandr, then repaint with the pace. If the refresh rate is 60Hz, we paint at most 60 times per second.

      Pros: Easy to implement, low cost, saves resources by delaying event processing and repainting.

      Cons: sleep() may not accurately work (I've seen poll() not sleeping accurately); If the repaint starts at a particular time, maybe screen tearing will increase instead of decrease.

    2. Relying on DRM_IOCTL_WAIT_VBLANK. Simulating the xfwm4 patch corenominal pointed out.

      Cons: DRM_IOCTL_WAIT_VBLANK is reported to be "downright broken" on some chips in some cases; No documentation I could find; I have idea if it will work on proprietary drivers; the author says there's 10 pixel tearing area, and I don't know if it could get larger under specific situations (like very high load).

    3. Using OpenGL VSync functionalities. Simulating cairo-compmgr and Compipz.

      Cons: Might be driver-dependent, Compiz's VSync feature at least used to be broken on some chips; OpenGL wiki says "Your application's use of swap interval may be overridden by external, driver-specific configuration"; Little documentation; Uncertain if will conflict with the VSync feature of the driver like what chjj said; Linking to libGL.

      And I'm not quite sure what is the correct interface to use. SGI_swap_control, SGI_video_sync, or GLX_OML_sync_control? And bitSphere says mesa and nVidia/ATI drivers use different functions.

  3. The biggest problem is lack of documentation... I could try writing some code but there won't be a way for me test on every sort of GPUs. We don't have many developers, and I guess we are not rich enough to have many computers with different GPUs.
  4. My current suggestion is to check your driver for VSync support. The nVidia binary blob provides a "Sync to VBlank" option for me and I don't seem getting any tearing.
@corenominal

I guess we are not rich enough to have many computers with different GPUs.

If you wanted to give option 1 a try, I have a bunch of different system I can test it on. Also, I think I could encourage a good few CrunchBang users to help with testing. Just a thought.

@richardgv
Collaborator

If you wanted to give option 1 a try, I have a bunch of different system I can test it on. Also, I think I could encourage a good few CrunchBang users to help with testing. Just a thought.

Honestly I thought Plan 1 is the worst of all. :-) I might try to implement if you are interested, but not too soon -- it doesn't have the highest priority and I started getting busy recently.

@Janhouse
Janhouse commented Oct 3, 2012

I don't have much free time but if you need some help with testing or something else, I could try finding some time for it.

I can test it on laptops with Radeon X1200 (open source driver only) and Intel (3rd Gen Core processor Graphics Controller) video cards.

@richardgv richardgv added a commit that referenced this issue Oct 8, 2012
@richardgv richardgv Feature: #7: VSync
- Add VSync feature. 3 possible VSync methods available: "sw" (software,
  not too reliable, but at least you have something to fallback to),
  "drm" (using DRM_IOCTL_WAIT_VBLANK, should work only on DRI drivers),
  "opengl" (using SGI_swap_control extension OpenGL, might work on more
  drivers than the DRM method). "sw" and "opengl" are briefly tested,
  "drm" received utterly no test (because I use the nVidia binary blob).
  They are enabled with "--vsync sw" / "--vsync drm" / "--vsync opengl".

- Add --refresh-rate to let user specify a refresh rate for software
  VSync, in case the automatic refresh rate detection does not work
  well.

- Seemingly the automatic refresh rate detection using X RandR in
  software VSync detects refresh rate incorrectly. Need further investigation.

- Fix a few bugs in fading timing.

- Add a workaround for client window detection on Fluxbox, as Fluxbox
  (incorrectly?) sets the override-redirect flag upon all frame
  windows.

- Software VSync adds dependency on librt (a part of glibc) for
  nanosecond-level timing functions, and libXrandr for automatic refresh
  rate detection; DRM VSync adds dependency on libdrm to use its drm.h,
  but does not link to libdrm; OpenGL VSync adds dependency on libGL.

- Print timing information on DEBUG_REPAINT.
b59e592
@richardgv
Collaborator

Here you go, guys. Clone richardgv-dev branch and test! Read the commit log or usage text for information for how to enable VSync. All 3 methods need testing, but especially the DRM one -- it's entirely not tested.

When you try the software VSync remember to use --refresh-rate to specify your refresh rate. Probably the refresh rate detection isn't working.

If you have the the interest to further investigate if the painting time is correct, compile compton with:

make clean; CFLAGS='-DDEBUG_REPAINT' make

And compton will print out the detailed time of painting like this:

[     0:020020472 ] [     7.38 ] paint: 0x00c00352 0x00c00661 0x00c076eb 0x00c04cb8 0x00c0397a
[     0:020006796 ] [     7.40 ] paint: 0x00c00352 0x00c00661 0x00c076eb 0x00c04cb8 0x00c0397a
[     0:019991037 ] [     7.42 ] paint: 0x00c00352 0x00c00661 0x00c076eb 0x00c04cb8 0x00c0397a
[     0:019996693 ] [     7.44 ] paint: 0x00c00352 0x00c00661 0x00c076eb 0x00c04cb8 0x00c0397a
[     0:019993656 ] [     7.46 ] paint: 0x00c00352 0x00c00661 0x00c076eb 0x00c04cb8 0x00c0397a
[     0:020007497 ] [     7.48 ] paint: 0x00c00352 0x00c00661 0x00c076eb 0x00c04cb8 0x00c0397a
[     0:020004597 ] [     7.50 ] paint: 0x00c00352 0x00c00661 0x00c076eb 0x00c04cb8 0x00c0397a

The things in the first bracket is the time passed since last paint, in the format of [ SECONDS:NANOSECONDS ]; the second is the time passed since the program starts. If you see the interval is always N times of a fixed value (200, 000, 000 nanoseconds in the case above, as compton thinks my refresh rate is 50Hz -- but in fact it's 60Hz, the detection didn't work correctly), VSync is working.

This feature will not be available as a configuration file option before I'm sure it's working.

@corenominal

Thank you for your continued work, @richardgv. The chipset on this machine (Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller) does not seem to support the DRM mode, but I have tested the sofware and opengl modes.

Visually, the opengl mode seems to be working better on this system, there is tearing but it happens at a static position on the screen. I guess it's a timing issue as to when compton starts because the tearing will be displayed at a different position on the screen, each time compton is invoked. If I am super lucky with my timing, it appears either at the very top or very bottom of screen and is only noticable when playing fullscreen video.

Using the software mode, the tearing is visable again in a single position on the screen, but moves slowley down until it reaches the bottom, then starts again from the top. I guess the timing is very slightly out?

I hope the above makes sense. Sorry I have not been able to provide any debug output, I will try and do some more testing on different systems tonight.

@richardgv
Collaborator

@corenominal:

The chipset on this machine (Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller) does not seem to support the DRM mode

The DRM VSync should work for Intel drivers. I believe the driver use DRI in the kernel, right? Please check what error message are you receiving. "vsync_drm_init(): Failed to open device." indicates compton had troubles opening /dev/dri/card0, and please check if there's anything under /dev/dri. Other error messages or no error message generally indicates a bug in my code.

Visually, the opengl mode seems to be working better on this system, there is tearing but it happens at a static position on the screen. I guess it's a timing issue as to when compton starts because the tearing will be displayed at a different position on the screen, each time compton is invoked.

Oh, well, cairo-compmgr uses quite a similar method, and it does not have a tearing problem when we do? The only difference I could see is cairo-compmgr is probably using X DBE extension for rendering. Hmm, should we implement the same thing?

Using the software mode, the tearing is visable again in a single position on the screen, but moves slowley down until it reaches the bottom, then starts again from the top. I guess the timing is very slightly out?

There are two problems here that I could not understand:

  1. I've did a test here with 50Hz refresh rate specified in software VSync. There is an inaccuracy of tens of thousand nanoseconds per paint, possibly because of the time that compton's calculation takes, and inaccuracy in ppoll(), but this inaccuracy does not accumulate, so it should not cause the tearing line to move continuous in one direction (but it should cause the tearing line to go back and forth), unless you specified the wrong refresh rate -- which will probably make the tearing line move much more speedy than what you saw -- or compton does not count time in the same speed of your monitor.
  2. Even if we have a timing issue in the program, I imagine the tearing line should disappear after it goes over the bottom edge of the screen, instead of rotating instantly.

And at last, I have no luck reproducing any tearing, still. My knowledge about the whole thing is... Close to none. Before I read this issue report, I had no idea what VSync is. When I neither have sufficient knowledge nor could actually see and test about this problem, I'm afraid you can't expect much from me. Let's hope chjj could spot what's wrong in my code.

@Janhouse
Janhouse commented Oct 8, 2012

Device is 00:02.0 VGA compatible controller: Intel Corporation 3rd Gen Core processor Graphics Controller (rev 09) on Macbook Air running ArchLinux Linux janhouse 3.6.0-1-ARCH #1 SMP PREEMPT Mon Oct 1 20:51:05 CEST 2012 x86_64 GNU/Linux

$ ./compton --vsync sw --refresh-rate 60

In sw mode it is tearing in different place each time I start compton.
If I start it at the right time it is hard to see tearing in VLC but I see it in http://www.youtube.com/watch?v=ZCPkOpMHB7g

Same command with debugging mode:

[     0:016670824 ] [    11.98 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165
[     0:016663557 ] [    12.00 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165
[     0:016659790 ] [    12.01 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165
[     0:016679815 ] [    12.03 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165
[     0:016661141 ] [    12.05 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165
[     0:033333099 ] [    12.08 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165
[     0:033365424 ] [    12.11 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165
[     0:016659622 ] [    12.13 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165
[     0:033304886 ] [    12.16 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165
[     0:016677879 ] [    12.18 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165
[     0:016714321 ] [    12.20 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061b1f6 0x0061b264 0x006104b4 0x00615165

$ ./compton --vsync opengl

I see tearing

With debugging:

[     0:016460135 ] [     5.12 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061af10 0x0061af7e 0x006104b4 0x00615165
[     0:016680112 ] [     5.14 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061af10 0x0061af7e 0x006104b4 0x00615165
[     0:022602128 ] [     5.16 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061af10 0x0061af7e 0x006104b4 0x00615165
[     0:017290292 ] [     5.18 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061af10 0x0061af7e 0x006104b4 0x00615165
[     0:010186604 ] [     5.19 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061af10 0x0061af7e 0x006104b4 0x00615165
[     0:020854538 ] [     5.21 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061af10 0x0061af7e 0x006104b4 0x00615165
[     0:012569494 ] [     5.22 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061af10 0x0061af7e 0x006104b4 0x00615165
[     0:033688256 ] [     5.26 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061af10 0x0061af7e 0x006104b4 0x00615165
[     0:016036658 ] [     5.27 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061af10 0x0061af7e 0x006104b4 0x00615165
[     0:016708235 ] [     5.29 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x00600d38 0x0061541d 0x0061af10 0x0061af7e 0x006104b4 0x00615165

$ ./compton --vsync drm

I see tearing

And with debugging:

[     0:016664764 ] [    10.00 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
[     0:016689692 ] [    10.01 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
[     0:016641894 ] [    10.03 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
[     0:033361276 ] [    10.06 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
[     0:016673573 ] [    10.08 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
[     0:016663371 ] [    10.10 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
[     0:033328853 ] [    10.13 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
[     0:033339222 ] [    10.16 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
[     0:016658948 ] [    10.18 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
[     0:016677822 ] [    10.20 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
[     0:016668543 ] [    10.21 ] paint: 0x006001a2 0x0060f623 0x00610477 0x00610877 0x006116f9 0x00611756 0x0061672b 0x0060a352 0x0061541d 0x00600d38 0x0061a6e2 0x00615165 0x0061a694 0x006104b4
@richardgv
Collaborator

Ah, I forgot to say, thanks for your tests. :-)

@Janhouse:

The good thing is I saw under both the sw mode and the drm mode, compton is painting with the correct timing. The opengl mode test result looks somewhat incorrect, but, hmm, it's working in both in corenominal's and my tests.

The bad thing is, looks like by controlling the timing of painting I only (mostly) successfully sticked the tearing line to a fixed place on the screen instead of removing it. Hmm, I have no idea what's wrong...

@richardgv richardgv added a commit that referenced this issue Oct 23, 2012
@richardgv richardgv Improvement #7: Add double buffering
Add double buffering with X DBE extension in hope to get rid of the
tearing issue. Thanks to cairo-compmgr for providing hints. Could be
enabled with --dbe. Only very limited tests have been done, I don't know
if it actually solves the tearing issue. My estimation is it is harmful
for performance, but I found no clear evidence. Experimental, so no
configuration file option is available for it.

MONITOR_REPAINT is broken if --dbe is turned on, this is intended for
testing whether DBE is actually working.
5dd544d
@richardgv
Collaborator

Alright, another attempt: Double buffering, stolen from cairo-compmgr. Please clone from richardgv-dev branch and run compton with a VSync method and --dbe, and test if the tearing changes somehow. (But I'm interested in the result when --dbe alone is enabled, too.) Although I don't think double buffering will cause a huge drop in performance, I still would recommend you guys to check for any possible performance issue caused by double buffering.

kwin does not seem supporting VSync at all in its XRender mode, and I'm unsuccessful in finding the VSync code in mutter. If double buffer fails to work... Are you guys aware of any other compositing window manager that supports VSync and uses XRender as backend?

@Janhouse

A quick test didn't show any improvements but then I started googling and found that many people have the tearing problem with those new Intel graphics cards. I installed some git versions for those drivers and will test if something changes after I reboot.
Will post how it goes after I test it.

@richardgv
Collaborator

Now it's the real problem why apparently VSync in cairo-compmgr is working for corenominal, but I cloned its VSync and it did not work... Is there still a tearing line appearing in a fixed place?

If you have some extra time, I hope you could do some tests to help the diagnostics:

  1. Try the git version of cairo-compmgr and see if it's tearing-free. I personally could not get the version working without segfault, somehow.
  2. Try commenting out line 1704 of ./src/compton.c, which is:
    XdbeSwapBuffers(dpy, &swap_info, 1);

Then compile, and run with:

./compton --dbe --vsync sw --refresh-rate 60

If everything goes right, all your windows will disappear, with only the root window (wallpaper) left. (Then you use Ctrl-C to terminate compton blindly.) This verifies if double buffering is actually working.

I'm still not sure about the process of how things are rendered to monitor, and why people are not able to stop tearing by starting compton in a specific range of time between refreshes with software VSync...

If I could not find a better solution I might have to let compton wait for one frame before painting so the tearing line, with the best luck, might stick to somewhere pretty close to the top of the screen. And that will still not work for software VSync...

Update: Ah, I saw this, which indeed probably points to a driver issue instead of a compositing window manager issue: http://www.phoronix.com/scan.php?page=news_item&px=MTIxMTM

But you see absolutely no tearing if compton is not running, right? Even with the unaccelerated x11 video output mode?

@richardgv
Collaborator

Another update:

Please clone from richardgv-dev and check if the painting-on-overlay support added in 049621b helps. Please test both --paint-on-overlay and --paint-on-overlay --dbe (of course, enable --vsync, too). Although I don't think they are much related, it at least simulates cairo-compmgr better.

@uzvermode

Latest richardgv-dev, trying all variants:

xubuntu 12.10
nvidia 310.14 (card GT240)

--vsync opengl --dbe
--vsync opengl --dbe --paint-on-overlay
--vsync opengl --paint-on-overlay

top half screen tearing

--vsync sw --refresh-rate 60 --dbe
--vsync sw --refresh-rate 60 --dbe --paint-on-overlay
--vsync sw --refresh-rate 60 --paint-on-overlay

tearing goes from top of screen to bottom with some delay

@richardgv
Collaborator

Very well then. I guess I've done pretty much what I could do, and eventually I have to ask somebody else. Let's hope the Xorg guys will bring us something impressive: http://lists.x.org/archives/xorg/2012-October/054996.html

Meanwhile, please check the OpenGL settings and XVideo settings in nvidia-settings, and enable their "Sync To VBlank", see if things changes.

Update:

Ah, I thought about a thing! Probably I have fundamentally misunderstand VSync. Will try to implement later.

@richardgv richardgv added a commit that closed this issue Oct 26, 2012
@richardgv richardgv Bug fix #7: Correct a possible issue in VSync
- I realized I might have fundamentally misunderstood VSync. This commit
  tries to fix the possible problem, or at least move the tearing line
  close to the top of the screen.

- Software VSync is replaced by --sw-opti (software optimization), as
  I guess it isn't possible at all to do VSync without driver support.

- Add "vsync" and "sw-opti" as configuration file options.
66e6157
@richardgv richardgv closed this in 66e6157 Oct 26, 2012
@richardgv richardgv reopened this Oct 26, 2012
@richardgv
Collaborator

Ah, GitHub, you are way too smart again!

Now please clone from richardgv-dev branch and test. I hope this commit could at least have some positive effects. The software VSync does not work as VSync, I believe, so it has been turned into --sw-opti (Software optimization), the syntax of the rest stays the same.

@uzvermode

With --vsync opengl --sw-opti options, even in video players (vdpau, xv) and flash, it's tears only on top of screen where my panel situated ^^. Great work:)
It's interesting the same problem in Kwin(4.8,4.9.1,4.9.2)https://bugs.kde.org/show_bug.cgi?id=307965

@richardgv
Collaborator

Thanks for your test, and your link. So all my efforts result in a situation not much better than the Xfce patch? Now I truly have no idea how to get rid of the tearing...

Have you actually tried --dbe after the commit, then? It would be depressing if --dbe --vsync opengl still has the tearing issue. Moving line 1727 in src/compton.c might slightly move the line closer to the top in non-DBE mode, but I want to see how DBE works firstly.

Kwin, when using XRender as backend, does not seem to even have VSync; its OpenGL backend probably uses double buffering (or triple buffering, etc.), which could have better performance than the X DBE double buffering, so if even Kwin with OpenGL backend is doing tearing... Oh, well, let's see what reply my question posted on Xorg mailing list will receive firstly before trying to decide anything.

By the way, haven't I warned that --vsync XXX and --sw-opti shouldn't be used together in the commit log? Effectively it generally causes no additional speed benefits but frame dropping.

By the way 2, have you actually looked into nvidia-settings as I recommended in one of the previous replies?

@uzvermode

Oops) nvidia-settings all vsync(xv, opengl)

--sw-opti (with / without dbe)

tearing whole screen

--vsync opengl (with / without dbe)

top of screen trearing, 10...18 px i think

@richardgv
Collaborator

Oh, 18px is big enough, even larger than that of the Xfce patch. Truly mysterious why I don't see tearing even if I turn all VBlank stuffs off. Oh, you have "Allow flipping" enabled in nvidia-settings, right? It could be useful for double buffering, I guess. And are you experiencing the tearing on other window managers? If you could find a tear-free one, I might be able to get something from its code.

By the way, somebody suggested VSync in nvidia-drivers does not work if the Performance level is 0, and adjusting the "PowerMizer settings" in the GPU panel of nvidia-settings fixed the issue for him. The link, among other possible fixes: http://askubuntu.com/questions/125245/how-do-i-stop-video-tearing-nvidia-prop-driver-non-compositing-window-manager

@uzvermode

Yes, "Allow flipping" option is enabled by default on new nvidia drivers.

Tear-free for me mutter / muffin (gnome-shell / cinnamon)

but i have some lag when dragging windows: window follow mouse pointer too slow (with some delay), this starts from gnome 3.5, and its awful in 3.6, same on cinnamon 1.*, windows looks so heavy)))

Also with compiz i had no tearing.

@tritonas00

Thank you for your great work!

Intel gma 3150 with --vsync opengl (archlinux - xf86-video-intel 2.20.12 and mesa 9.0)

Finally my netbook runs almost tear-free with openbox and compton ! Also no tearing in videos !

I say almost because I only have tearing at the very top of the screen.

I will test it in my desktop with nvidia 9600 and let you informed.

@corenominal

Sorry for the delay in providing feedback, work has been manic. Anyhow, nice job work, @richardgv, and thank you! Using compton --dbe --vsync opengl works really well, the tearing line is pinned to the top of my screen and during normal operation is completely invisible. Brilliant!

@richardgv
Collaborator

@funeral1988:

Also with compiz i had no tearing.

Yep, OpenGL buffer swap could be faster than X DBE buffer swap...

Tear-free for me mutter / muffin (gnome-shell / cinnamon)

Mutter uses clutter too much that makes its code harder to read. Well, I will see if I could get something.

Update: Clutter is OpenGL based, as far as I can see. It never actually mentions "XRender". So, we probably can't borrow much from mutter this time.

@tritonas00: Thanks for you feedback. :-)

@corenominal: Thanks. Yeah, a tearing line on the top, that cannot be removed... Has cairo-compmgr successfully fixed all the tearing issue?

@uzvermode

@richardgv:
good to hear), u already did great job! thx

Mutter uses clutter too much that makes its code harder to read. Well, I will see if I could get something.

the most important issue after i stop using gnome-shell and cinnamon its delayed movement windows (on gnome 3.6 its terrible) and i can't find any information about that, its nvidia blob's problem or not,i don't know, and its little scares me that u'll using some peace of code from mutter project.

@richardgv
Collaborator

@funeral1988:

Huh, clutter looks entirely OpenGL based. Most likely we cannot port its rendering code to XRender-based compton.

Right now my estimation is the VBlank interval is too short and XRender/X DBE is not painting fast enough (or schedules painting of compton after some other tasks), causing tearing on the top of the screen, while OpenGL, with direct access to the driver, does this much faster. But it's just my estimation.

the most important issue after i stop using gnome-shell and cinnamon its delayed movement windows (on gnome 3.6 its terrible) and i can't find any information about that, its nvidia blob's problem or not,i don't know, and its little scares me that u'll using some peace of code from mutter project.

It could be an issue of the performance of your GPU. We had multiple reports about delayed window movements, and they point to GPU performance from appearance. (At least, they said it went away after I reduced painting requests compton sends and the painting region.) Maybe mutter is just doing too much abundant drawing on the screen.

@OrdinaryMagician

After cloning from the richardgv-dev branch, with no parameters other than --vsync opengl I can confirm that:

  • There's practically no drops in performance both on games and video playback.
  • There are no sudden frame drops.
  • X server CPU usage stays around 1~2 percent.
    I'm on a 560Ti with the latest beta drivers from NVIDIA, running Arch Linux x86_64.
@glesik
glesik commented Oct 31, 2012

I just tested the latest build of richardgv-dev branch with Intel x3100 and 2.20.8 driver on Fedora 17 and see the following:

  • --vsync drm: tearing is now fixed at ~150px from the top (1280x800px resolution);
  • --vsync opengl: tearing zone appears at ~150px from the top, scrolls up and disappears for ~10s, then everything repeats;
  • --dbe option doesn't seem to change the behavior.
@richardgv
Collaborator

Well, I should have carefully read the Xfwm4 VSync patch earlier... I pushed another commit, fb2ca16, to richardgv-dev, that may or may not move the tearing line upward. Please test if the commit helps in some ways (or make things worse in some ways). There's a commandline switch added, --vsync-aggressive, that may have either slightly positive or very negative effects on VSync, and please also test that. (The commit improves VSync even without --vsync-aggressive, so please test both with and without --vsync-aggressive.)

@OrdinaryMagician:

Huh, thank you. :-)

There's practically no drops in performance both on games and video playback.

Well, if you turn off OpenGL "Sync to VBlank" in nvidia-settings, and run glxgears with and without compton running, I believe you will observe the difference from the FPS. The performance does drop anyway...

There are no sudden frame drops.

If you are talking about frames being skipped over when compton is running (or you mean FPS drops?), then yes, compton's VSync is known (theoretically) to have the possibility of causing frame drops (we may reduce this in a certain degree if we use multithreading), but the frame drops are barely noticeable, as without supernatural power, human eyes can't read 60 frames per second.

X server CPU usage stays around 1~2 percent.

Ah, that doesn't look bad. :-)

@glesik: Ah, thanks. And 150px is moderately long to be annoying for you, I bet? Could you please test if the latest commits help?

tearing zone appears at ~150px from the top, scrolls up and disappears for ~10s, then everything repeats;

Huh, I really have no idea why that thing would move...

@OrdinaryMagician

@richardgv

Well, if you turn off OpenGL "Sync to VBlank" in nvidia-settings, and run glxgears with and without compton running, I believe you will observe the difference from the FPS. The performance does drop anyway...

Yes, there's a drop from 19765 to 13698 FPS, but I do believe it's not practically noticeable. Besides, making the GPU do more work than it needs isn't good either way.

If you are talking about frames being skipped over when compton is running (or you mean FPS drops?), then yes, compton's VSync is known (theoretically) to have the possibility of causing frame drops (we may reduce this in a certain degree if we use multithreading), but the frame drops are barely noticeable, as without supernatural power, human eyes can't read 60 frames per second.

I was actually talking about cases where suddenly the framerates would drop below 1 FPS for some seconds causing the screen to become garbled with excessive tearing. It was the main reason I had stopped using composition in the first place.

Actually, it seems to still happen, but more softly. I was playing Dishonored last night, fullscreen, and after 20 minutes I noticed the framerate was quite low (but not to the point of becoming a "slideshow"), alt-tabbing and checking the task manager showed that X was using about 15% CPU, and didn't stop until I restarted compton.

@richardgv
Collaborator

@OrdinaryMagician:

Hey, do you actually have a tearing issue and needs VSync? If you have the issue, please read the top part of my last comment.

Yes, there's a drop from 19765 to 13698 FPS, but I do believe it's not practically noticeable. Besides, making the GPU do more work than it needs isn't good either way.

6,000 FPS drop, huh...

I was actually talking about cases where suddenly the framerates would drop below 1 FPS for some seconds causing the screen to become garbled with excessive tearing. It was the main reason I had stopped using composition in the first place.

Actually, it seems to still happen, but more softly. I was playing Dishonored last night, fullscreen, and after 20 minutes I noticed the framerate was quite low (but not to the point of becoming a "slideshow"), alt-tabbing and checking the task manager showed that X was using about 15% CPU, and didn't stop until I restarted compton.

Well, compton is known to use more CPU than xcompmgr, but it may stress the GPU less. I personally almost never play games on Linux, and I don't know the "frame dropping" thing.

X is using 15% CPU? Well, and the rest 85% are all occupied or not? You have to figure out where the bottleneck is, the CPU or the GPU. X using 15% CPU is not too surprising, anyhow. I've seen X using 20%+ during some activities without compton running.

So are you experiencing frame dropping with other compositing window managers? xcompmgr, too?

2 users already reported compton is causing high CPU usage on the X process after long time of usage, but it's so hard to reproduce and debug... Link: #50 (comment)

I may add a feature that let compton stop compositing if it detects a fullscreen window later, also.

@OrdinaryMagician

@richardgv

Hey, do you actually have a tearing issue and needs VSync?

I can't quite understand what you've said, sorry.

6,000 FPS drop, huh...

As long as the framerate is still much higher than the screen refresh rate, it doesn't matter much.

X is using 15% CPU? Well, and the rest 85% are all occupied or not? You have to figure out where the bottleneck is, the CPU or the GPU. X using 15% CPU is not too surprising, anyhow. I've seen X using 20%+ during some activities without compton running.

Well, the rest of CPU was unoccupied by then.

So are you experiencing frame dropping with other compositing window managers? xcompmgr, too?

I run Openbox standalone. Haven't actually tested other WMs or composite managers and I guess I'm too lazy to do so.

I may add a feature that let compton stop compositing if it detects a fullscreen window later, also.

That sounds nice, I'm looking forward to it.

@richardgv
Collaborator

@OrdinaryMagician:

I can't quite understand what you've said, sorry.

Sorry, my English isn't great. I meant, if you do see tearing when playing videos with compton running, please follow my advices in the next-to-last reply, to pull and build from richardgv-dev branch right now and test if my latest commits help, and test if --vsync-aggressive switch has some effect over the position of the tearing line. If you didn't meet the tearing issue, please discuss in #50 instead. This issue report primarily is for discussing about the tearing issue.

As long as the framerate is still much higher than the screen refresh rate, it doesn't matter much.

A frame in a game takes much more resources than a frame in glxgears. 6,000 FPS is roughly 1/3 of your total FPS, so it generates a 33% performance penalty, which could be troublesome when you are playing a game with higher requirement on GPU.

Well, the rest of CPU was unoccupied by then.

Then your bottleneck is GPU? Then I guess I can't do much. compton is almost doing minimal painting, I suppose. I have no idea how the driver and the graphic card are working, and I don't know where could still be optimized on the GPU side.

@OrdinaryMagician

@richardgv
ah... sorry, I'll go there then.

@tritonas00

No tearing on my nvidia 9600 (archlinux, compton --vsync opengl)

Great ! Can i ask, when are u going to move the code to master branch ?

Thanks!

@Janhouse
Janhouse commented Nov 1, 2012

I get almost no tering with --vsync opengl --sw-opti with 00:02.0 VGA compatible controller: Intel Corporation 3rd Gen Core processor Graphics Controller (rev 09).

The top part of the video is tearing in fullscreen Youtube (flash) videos but it is not that annoying as it was when it happened in the middle of the screen.
And it is not tearing in VLC anymore so I am pretty happy with the results. :)

Oh and in one moment the whole UI started lagging and became really unresponsive and went back to normal only when I killed compton. Not sure if something is leaking but I just wanted to mention this in case someone else notices it. It happened only once so far so no clue where it came from and how to reproduce it.

@richardgv
Collaborator

@tritonas00:

Ah, awesome, thank you. :-)

Great ! Can i ask, when are u going to move the code to master branch ?

A series of aggressive changes has been pushed into richardgv-dev branch recently, and it is my plan to review the patches in #59 and merge it later, which is going to be a risky change. And as we have no formal release for now, many distros are pulling from the master branch. Overall, it's not too likely that the richardgv-dev branch is to be merged into master really soon, sorry.

@Janhouse:

Ah, cool, thanks. :-)

The top part of the video is tearing in fullscreen Youtube (flash) videos but it is not that annoying as it was when it happened in the middle of the screen.

Have you tried the --vsync-aggressive flag added to richardgv-dev branch yesterday? I will remove that if people report it has no effect or negative effects.

Oh and in one moment the whole UI started lagging and became really unresponsive and went back to normal only when I killed compton. Not sure if something is leaking but I just wanted to mention this in case someone else notices it. It happened only once so far so no clue where it came from and how to reproduce it.

You are 4th or the 5th person complaining about the mysterious slowdown. Well, I will finish my serious (and boring) work today, look into the more annoying #59 tomorrow, and I may only have time after tomorrow to try to let compton continuously run until I could reproduce this issue.

@Janhouse
Janhouse commented Nov 2, 2012

That slowdown bug happens only after some long time and in my case when Firefox and Chrome is open (each with about 30 open tabs). RAM is not full and X and compton is not even in top 5 of ram usage list.

@richardgv
Collaborator

@Janhouse:

Thank you. :-) I've pushed a (again, possible) fix for the problem to richardgv-dev branch. The whole story and the things I want to say to anybody who is encountering the issue is here: #50 (comment)

If X is using not much memory, it could indicate the chance of a Picture leak is not high, at least.

@glesik
glesik commented Nov 3, 2012

For me --vsync-aggressive only made things worse: the tearing zone now slowly scrolls up all across the screen for ~12 seconds (pretty much like with --vsync none). But I think that clarifies a little the behavior I described before: with --vsync opengl the zone is moving the same way, but tearing itself is visible only within top ~150px.

By the way, both opengl and drm have the same result now: tearing scrolls but is visible only on the top.

@richardgv
Collaborator

@glesik:

For me --vsync-aggressive only made things worse: the tearing zone now slowly scrolls up all across the screen for ~12 seconds (pretty much like with --vsync none). But I think that clarifies a little the behavior I described before: with --vsync opengl the zone is moving the same way, but tearing itself is visible only within top ~150px.

By the way, both opengl and drm have the same result now: tearing scrolls but is visible only on the top.

Thanks for testing. :-)

I wasn't expecting --vsync-aggressive to work at all. I just don't understand why the xfwm4 VSync patch uses that. Once I receive another negative report I will remove it.

I still couldn't comprehend why the tearing line would move in that way, but, well, it's pretty much the furthest I could get to in the VSync issue. Nobody is replying to my VSync question on xorg user mailing list. You probably have to bear the 150px tearing unless you switch to a OpenGL-based compositing window manager.

@jeroenost

Also I have thoroughly tested the latest version (I hope the correct one - git master).
I am using via_chrome9 drivers, which are based on open source intel drivers and support dri/drm wait for vblank.
Xfwm4 with tearing patch was "sort of" working, but stopped working after I recently upgraded webkitgtk. Compton solves tearing for me with this new webkit, so I switched.

compton --vsync=drm --dbe is giving me the best results (slight tearing in top 100 pixels in <1% of the time, no tearing in 90% of the time and top 20 pixels tearing in the rest of the time.
vsync-aggressive is screwing things up.
compton --vsync opengl slightly worse by=ut also works acceptable.
compton --drm without --dbe is comparable.
--paint-on-overlay doesn't seem to influence it either.

@richardgv
Collaborator

@jeroenost:

Thank you for your tests, jeroenost!

I am using via_chrome9 drivers, which are based on open source intel drivers and support dri/drm wait for vblank.

Huh, sorry, but are you talking about xf86-video-openchrome, xf86-video-unichrome, the VIA Unichrome DRM module in kernel, the VIA broken proprietary drivers, or something else?

Xfwm4 with tearing patch was "sort of" working, but stopped working after I recently upgraded webkitgtk. Compton solves tearing for me with this new webkit, so I switched.

I don't really understand how webkit-gtk could be related to VSync in xfwm4...

Basically we use the same approach as the xfwm4 patch does (well, even a bit weaker), so they should have roughly the same effect.

compton --vsync=drm --dbe is giving me the best results (slight tearing in top 100 pixels in <1% of the time, no tearing in 90% of the time and top 20 pixels tearing in the rest of the time.
vsync-aggressive is screwing things up.
compton --vsync opengl slightly worse by=ut also works acceptable.
compton --drm without --dbe is comparable.
--paint-on-overlay doesn't seem to influence it either.

I'm glad to see it works acceptably on your system. :-) Huh, too bad I couldn't improve it further.

@jeroenost

Via has recently released open source drivers on http://linux.via.com.tw/support/downloadFiles.action
I am using driver version 5.76.52.92-003-68680. They released source code for both module and xorg driver. The hardware acceleration is fine and quite performant.
Some context: I am building an application where we display full screen video with a HTML5 overlay, rendered by webkitgtk with a transparant background. Up until recently I was using an old version of webkitgtk 1.6.3 with VLC for the video. For font anti aliassing with the background and some transparency effects, it is important I have compositing between the two windows. With VLC set to XVideo out on adaptor XV_TEXTURE (which has compositing), I never could get rid of tearing. I only managed to get rid of it by using VLC OpenGL output, in combination with xfwm4's tearing patch.
Recently I had to upgrade webkit to a newer version (1.10.2) because of segfaults in the old webkit.
I noticed tearing got terribly worse. That seems very unlogical, I know. I made a couple of theories.
Perhaps webkit is also trying to use glxSwapBuffers or any other OpenGL vsync method.
Another theory is that webkit 1.10.2 is using the gtk main loop a lot more for timers, leave less time and more inpredictable behaviour for scheduling timers.
Either way, with xfwm4 tearing is, and with compton it's better. I didn't know about compton earlier, but I must say I like it. xfwm4 was way too much overhead and functionality. Compton is lighter.
I will see if I can spend some time in the code to improve things.

What exactly is --paint-on-overlay supposed to do ?
Because what I saw is that both with Intel and VIA drivers (comparing both has learned me that VIA bases their drivers at least partly on Intel code) , there are two XVideo adaptors. The first one, XV_SWOV is actually using an overlay to display video and is by design tear-free (totally). It doesn't composite though. The second one, XV_TEXTURE has compositing but is suffering from tearing. I would like to create an approach where we do the compositing ourselves, then use XV_SWOV to display the end result.

"xvinfo" gives more info on both.

I will look into the compton code when I have some time.

@jeroenost

Further testing today has showed me that I get best, almost perfect results by

  • disabling kernel preemption (CONFIG_PREEMPT) (keeping CONFIG_PREEMPT_VOLUNTARY=y). I haven't tried changing the latter to N as well.
  • compton --vsync drm --paint-on-overlay
    paint-on-overlay is eliminating the sporadic tearing I saw around 50-100px from the top. Now it seems only <10px from the top and very very seldom (fast moving action scenes where the camera swipes left/right)

--sw-opti and --vsync-aggressive are making tearing slightly worse.

This is really nice work. Thanks a lot.

@richardgv
Collaborator

Via has recently released open source drivers on http://linux.via.com.tw/support/downloadFiles.action
I am using driver version 5.76.52.92-003-68680. They released source code for both module and xorg driver. The hardware acceleration is fine and quite performant.

Ah, thanks for info, I didn't know that. I had a few years of experience with a VIA UniChrome Pro IGP and the openchrome driver, and it definitely wasn't the greatest driver I've seen. Glad to see VIA is back working on this.

Some context: I am building an application where we display full screen video with a HTML5 overlay, rendered by webkitgtk with a transparant background. Up until recently I was using an old version of webkitgtk 1.6.3 with VLC for the video. For font anti aliassing with the background and some transparency effects, it is important I have compositing between the two windows. With VLC set to XVideo out on adaptor XV_TEXTURE (which has compositing), I never could get rid of tearing. I only managed to get rid of it by using VLC OpenGL output, in combination with xfwm4's tearing patch.
Recently I had to upgrade webkit to a newer version (1.10.2) because of segfaults in the old webkit.
I noticed tearing got terribly worse. That seems very unlogical, I know. I made a couple of theories.
Perhaps webkit is also trying to use glxSwapBuffers or any other OpenGL vsync method.
Another theory is that webkit 1.10.2 is using the gtk main loop a lot more for timers, leave less time and more inpredictable behaviour for scheduling timers.

Seemingly, WebKit does have VSync code in ./platform/graphics/chromium/cc/CCFrameRateController.*, but it's in the chromium-specific graphic part. I don't really know whether GTK+/cairo does some VSync.

I will look into the compton code when I have some time.

Cool. :-) vsync_drm_wait() and vsync_opengl_init() are the functions that waits for VSync.

What exactly is --paint-on-overlay supposed to do ?

--paint-on-overlay lets compton paint on the X Composite overlay window. X Composite protocol specification describe this window as:

Version 0.3 of the protocol adds the Composite Overlay Window, which
provides compositing managers with a surface on which to draw without
interference. This window is always above normal windows and is always
below the screen saver window. It is an InputOutput window whose width
and height are the screen dimensions. Its visual is the root visual
and its border width is zero. Attempts to redirect it using the
composite extension are ignored. This window does not appear in the
reply of the QueryTree request. It is also an override redirect window.
These last two features make it invisible to window managers and other X11
clients. The only way to access the XID of this window is via the
CompositeGetOverlayWindow request. Initially, the Composite Overlay
Window is unmapped.

As far as I know, most compositing window managers (except xcompmgr and some of its derivatives) paints to this window by default. X.org probably is actually copying the content from the composite window back to the root window, but I'm not too sure about the details in implementation of the composite window.

Further testing today has showed me that I get best, almost perfect results by

  • disabling kernel preemption (CONFIG_PREEMPT) (keeping CONFIG_PREEMPT_VOLUNTARY=y). I haven't tried changing the latter to N as well.
  • compton --vsync drm --paint-on-overlay paint-on-overlay is eliminating the sporadic tearing I saw around 50-100px from the top. Now it seems only <10px from the top and very very seldom (fast moving action scenes where the camera swipes left/right)

Thanks. :-) Would you mind if I put this on wiki as your experience might be helpful for others?

--sw-opti and --vsync-aggressive are making tearing slightly worse.

--sw-opti should not be used with --vsync, by the way. --vsync essentially does --sw-opti's job already. I forgot to mention that in man page.

@jeroenost

Of course I don't mind. Will keep you posted.

@kunitoki

i experience tearing with my Nvidia GeForce GT425M too, no matter what i do with the options.

just found this: http://dri.freedesktop.org/wiki/CompositeSwap ...maybe helps in figuring out other ways to properly vsync

@richardgv
Collaborator

@kunitoki:

  1. I would prefer you to be a little more specific when reporting an issue. By describing your problem very obscurely one effectively wastes time of him and the developer. And it's a very bad habit indeed to blame the developer in the first place without carefully evaluating the situation.
    1. Are you using nouveau, or the nVidia binary blob? If nouveau lacks support for the underlying VSync mechanisms we rely on, we can't guarantee anything on it.
    2. Are you using a latest version of the driver? Have you noticed a different situation when you were using the older drivers?
    3. Does tuning driver settings help? In particular, the "Sync to VBlank" options in nvidia-settings, for the binary blob?
    4. Have you tried different video output? Are you using x11 output, xv output, vdpau output, or something else? Some of those output methods may be beyond compton's control.
    5. What configuration options do you use aside from the VSync options? Have you tried using no other options except --vsync (compton --config /dev/null --vsync opengl)?
    6. Do you get any warning messages with any of the VSync options enabled?
    7. How does the tearing look? Does it stay in one position or moves? Does different VSync methods have an effect on this?
    8. Does --paint-on-overlay or --dbe change anything?
    9. Have you tried --vsync-aggressive?
    10. On which applications have you noticed the tearing problem? Does using an alternative help?
  2. I did read the page you provided, kunitoki, months ago. But probably due to my lack of knowledge on X and OpenGL, I'm not able to understand much part of it. We are already using SGI_video_sync for OpenGL VSync. For the rest I'm not really sure.
@kunitoki

I would prefer you to be a little more specific when reporting an issue. By describing your problem
very obscurely one effectively wastes time of him and the developer. And it's a very bad habit
indeed to blame the developer in the first place without carefully evaluating the situation.

Hey ! I'm not blaming you, just reporting that i have some issues with tearing when moving windows and with fullscreen videos... i'm trying to help as much as i can, sorry for this

Are you using nouveau, or the nVidia binary blob? If nouveau lacks support for the underlying VSync
mechanisms we rely on, we can't guarantee anything on it.
Are you using a latest version of the driver? Have you noticed a different situation when you were
using the older drivers?

i'm using the binary x11-drivers/nvidia-drivers-318.18 and i had the same situation on the previous version too (310.19).

Does tuning driver settings help? In particular, the "Sync to VBlank" options in nvidia-settings, for the binary blob?
It doesn't help, with or without (also tried mixing it with compoton options but nothing seems change).

Have you tried different video output? Are you using x11 output, xv output, vdpau output, or something else?
Some of those output methods may be beyond compton's control.

I tried every video output:

  • x11 it's bad tearing (the worse)
  • xv it's slightly better but still worse
  • glx it's the better one (tearing on the higher part of the screen)

What configuration options do you use aside from the VSync options? Have you tried using no other
options except --vsync (compton --config /dev/null --vsync opengl)?
Do you get any warning messages with any of the VSync options enabled?
How does the tearing look? Does it stay in one position or moves? Does different VSync methods have
an effect on this?
Does --paint-on-overlay or --dbe change anything?
Have you tried --vsync-aggressive?

I have tried with --vsync=opengl which makes things better (tearing at fixed screen on top, about 300-350 pixels from top). I have my monitor running at 59.94hz (reported by xrandr and nvidia-settings) so i thought that with --refresh-rate=60 in compton there were some sync issues with redrawing. So i switched on using 50hz on the video card and setup --refresh-rate=50 (with and without --vsync=opengl mixed with or without --vsync-aggressive) but i still get tearing.
Tried to add --paint-on-overlay or --dbe mixed with all the previous options, enabled one by one but nothing better.
if you want i can make every option possibility with the result if you want.

On which applications have you noticed the tearing problem? Does using an alternative help?

I get tearing when moving windows (which you can hardly notice but there it is). The worse problem is full screen video applications (vlc, mplayer, xbmc)

@richardgv
Collaborator

@kunitoki:

Hey ! I'm not blaming you, just reporting that i have some issues with tearing when moving windows and with fullscreen videos... i'm trying to help as much as i can, sorry for this

My apology, kunitoki, I was obviously in a very bad mood last night (mostly due to all the annoyances in the D-Bus thing), and I lost patience immediately when I saw you reported a problem with almost no information.

  1. A tearing line staying at a fixed place generally means the VSync feature is taking effect. As you could see from the replies above, for some people the tearing line is pretty high (10-100 px from the top), but your situation is on the worst end.
  2. Somehow I got the impression that tearing problem happens most frequently on low-end cards. (And I've stated above, on my GTX 670 I never see tearing, with VSync or without.)
  3. As what I've stated in previous replies, it's rumored that selecting "Prefer Maximum Performance" in "PowerMizer" panel of nvidia-settings helps. jeroenost says disabling CONFIG_PREEMPT in kernel config is helpful. The "Timer frequency" and tickless settings in kernel may also affects this. Keep in mind that they probably will increase power consumption or make your GPU overheat.
  4. --refresh-rate is used only for --sw-opti, and --sw-opti is incompatible with --vsync. Please ignore --refresh-rate.
  5. Have you tried other compositors? Compiz, cairo-compmgr, mutter, and kwin all have VSync features. Do they work for you? And xcompmgr?
  6. Please check if your GPU is overloaded when the tearing appears. nvidia-smi might display some info. If it doesn't show the usage rate, you could look into GPU temperature and PowerMizer info in nvidia-settings. For example, it's a bad sign if you are using "Adaptive" PowerMizer mode but the performance level is always on the highest with compton running, or the temperature goes very high after 30 minutes of video playback. If your GPU is overloaded, try disabling more features in compton.
  7. Make sure your CPU is not 100% occupied, as well.
  8. The problem does not appear without a compositor running, right?
  9. Just an additional check: You have not modified other parts in nvidia-settings, right? You don't have extraordinary screen setups (e.g. multiple screens), do you?
  10. Should you read all the replies above, you would discover that due to our XRender backend many VSync methods do not work for us, and I've asked on xorg-users mailing list but nobody replied. I will try to find extra ways to improve our VSync feature, but as far as we still use X Render, I'm afraid you can't except me to find a VSync method that works perfectly.
  11. By the way, I've added D-Bus support to compton. Have you checked it out? See #80 for more info.

I tried every video output:

  • x11 it's bad tearing (the worse)
  • xv it's slightly better but still worse
  • glx it's the better one (tearing on the higher part of the screen)

That's a bit weird, I thought x11 would behave the best!

I get tearing when moving windows (which you can hardly notice but there it is). The worse problem is full screen video applications (vlc, mplayer, xbmc)

When moving windows? Ah, that's definitely sickening.

Regarding full-screen video playback, you could check if --unredir-if-possible helps. It unredirects the screen when it finds a full-screen window.

@richardgv richardgv added a commit that referenced this issue Jan 30, 2013
@richardgv richardgv Improvement #7: Add GLX_OML_sync_control VSync support
- Add "vsync-oml" VSync method, using GLX_OML_sync_control. Untested,
  because it's not supported by my driver.

- Unredirect ps->reg_win, because DRI wiki says it's related to the
  behavior of OpenGL VSync extensions.

- Add glFlush() and glXWaitX() calls, in hope they are slightly helpful
  for VSync.

- Change a few functions to make error handling more graceful. Make some
  errors fatal. Code clean-up.

- Add unused function make_text_prop().
1b5273c
@richardgv
Collaborator

I've just added a new VSync method (opengl-oml) to compton, in richardgv-dev branch, as well as some changes that may affect OpenGL VSync. (If I'm careless enough, it's possible that this commit introduces regressions in DRM VSync as well.) Could you please report the positive/negative effect of this commit and how --vsync opengl-oml works? (Especially you, @kunitoki.)

I couldn't test --vsync opengl-oml myself. nvidia-drivers does not support the OpenGL extension, as far as I know.

Another thing I'm considering is using OpenGL to do the last rendering step, which hopefully could eliminate tearing just like all those OpenGL compositors. However, I do not know whether OpenGL could somehow read from X Render Picture, and whether it accepts X Fixes clipping region.

@tsmithe
tsmithe commented Mar 11, 2013

Hi there; I've just started using compton, and it's certainly pretty great. However, I am on intel hardware, and so have quite a lot of tearing. I've done some research, and found a couple of links that might be useful for solving the problem -- I noticed your e-mail to the xorg list went unanswered:

[1] https://bugs.freedesktop.org/show_bug.cgi?id=37686
[2] https://bugs.kde.org/show_bug.cgi?id=307965#c100

[1] is very long, and you can get the important bits (it seems) from down near the bottom. [2] seems to be the comment (on a Kwin bug) after which most of the matter is clear.

I've tried all the current vsync methods, in combination with various VLC output settings. Currently, under 0.0.9+1git20130311-0ppa1~13.04 from your PPA, there is still tearing. Also, the most recent update seems to have removed the ability to combine the opengl-oml vsync method with painting on the overlay.

I don't understand the technicalities behind all this, wont as I am to; it would be nice if the documentation could go deeper into what the various rendering switches actually mean conceptually. I don't really know what "paint on overlay" or "dbe" are, so I can't really judge what sort of effect they might have. On the other hand, I can look up the GLX, OML and DRM sync methods, so that is clearer.

Thanks for your work, and if there's anything else I should add just say,

Toby

@richardgv
Collaborator

@tsmithe:

Just a quick reply: It's midnight here, I will have to sleep soon.

Hi there; I've just started using compton, and it's certainly pretty great.

Thanks. :-)

However, I am on intel hardware, and so have quite a lot of tearing. I've done some research, and found a couple of links that might be useful for solving the problem -- I noticed your e-mail to the xorg list went unanswered:

[1] https://bugs.freedesktop.org/show_bug.cgi?id=37686
[2] https://bugs.kde.org/show_bug.cgi?id=307965#c100

[1] is very long, and you can get the important bits (it seems) from down near the bottom. [2] seems to be the comment (on a Kwin bug) after which most of the matter is clear.

I will look into those, but trust me, I've done a lot of research already.

I've tried all the current vsync methods, in combination with various VLC output settings. Currently, under 0.0.9+1git20130311-0ppa1~13.04 from your PPA, there is still tearing.

Yes, of course there is tearing. compton's --vsync is known to be unable to eliminate tearing, it could only move the tearing line to the top region of the screen -- hopefully. X Render doesn't provide a VSync mechanism, so we are doing this in the ugly way. I think there's probably little we could do unless we start using OpenGL backend and glXSwapBuffers(). I'm still learning OpenGL now...

Also, the most recent update seems to have removed the ability to combine the opengl-oml vsync method with painting on the overlay.

Oops, sorry, this is a bug. Reversing the order of the vsync_init() call and init_overlay() call will fix this. I will push it tomorrow.

I don't understand the technicalities behind all this, wont as I am to; it would be nice if the documentation could go deeper into what the various rendering switches actually mean conceptually. I don't really know what "paint on overlay" or "dbe" are, so I can't really judge what sort of effect they might have. On the other hand, I can look up the GLX, OML and DRM sync methods, so that is clearer.

For --paint-on-overlay, please read the "Composite Overlay Window" section of compositeproto.txt of Xorg: http://cgit.freedesktop.org/xorg/proto/compositeproto/tree/compositeproto.txt

--dbe is about X DBE extension. The first part of this document should give you some insight about this: http://www.x.org/releases/X11R7.6/doc/libXext/dbelib.html

Really, I don't think a user should know that much! :-D Just check which one works best, that's usually enough.

Thanks for your work, and if there's anything else I should add just say,

I would personally like to know the position of the tearing line with each combination of the various --vsync options, --paint-on-overlay, and --dbe. Basically, which one works the best (tearing line closest to the top of the screen).

@tsmithe
tsmithe commented Mar 11, 2013

Hi Richard,

On 11 March 2013 16:04, Richard Grenville notifications@github.com wrote:

Yes, of course there is tearing. compton's --vsync is known to be unable to eliminate tearing, it could only move the tearing line to the top region of the screen -- hopefully. X Render doesn't provide a VSync mechanism, so we are doing this in the ugly way. I think there's probably little we could do unless we start using OpenGL backend and glXSwapBuffers(). I'm still learning OpenGL now...

Hmm, yes. It seems that would probably be the only way indeed, from
what I've read (and you're much more knowledgable than I!); I think
that's what the KWin people have done[0].

[0] https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/6072b4feb8c90024aa24b2e9cb8a21ab2140412c

Oops, sorry, this is a bug. Reversing the order of the vsync_init() call and init_overlay() call will fix this. I will push it tomorrow.

Great; thanks. That combination did seem so far to have the best
effect in reducing tearing.

For --paint-on-overlay, please read the "Composite Overlay Window" section of compositeproto.txt of Xorg: http://cgit.freedesktop.org/xorg/proto/compositeproto/tree/compositeproto.txt

Thanks -- that was enlightening. So, when you paint on the overlay
window (which I take just to be a special window on top of all the
others), as determined by this --paint-on-overlay switch, what do you
paint there that is different from before (ie, different from without
the switch)?

--dbe is about X DBE extension. The first part of this document should give you some insight about this: http://www.x.org/releases/X11R7.6/doc/libXext/dbelib.html

Ok, great. Does this mean that --dbe entails double graphics memory use?

Really, I don't think a user should know that much! :-D Just check which one works best, that's usually enough.

Hah, indeed. But I'm a curious fellow :-)

I would personally like to know the position of the tearing line with each combination of the various --vsync options, --paint-on-overlay, and --dbe. Basically, which one works the best (tearing line closest to the top of the screen).

I'll get back to you with some (probably anecdotal) data when you've
pushed the change tomorrow.

Regards,

Toby

@richardgv richardgv added a commit that referenced this issue Mar 12, 2013
@richardgv richardgv Bug fix: Create OpenGL context only after initializing overlay
- Create OpenGL context only after initializing overlay, which fixes a
  bug that --paint-on-overlay does not work with OpenGL VSync. Thanks to
  tsmithe for reporting. (#7)
4bc3de8
@richardgv
Collaborator

Yes, of course there is tearing. compton's --vsync is known to be unable to eliminate tearing, it could only move the tearing line to the top region of the screen -- hopefully. X Render doesn't provide a VSync mechanism, so we are doing this in the ugly way. I think there's probably little we could do unless we start using OpenGL backend and glXSwapBuffers(). I'm still learning OpenGL now...

Hmm, yes. It seems that would probably be the only way indeed, from
what I've read (and you're much more knowledgable than I!); I think
that's what the KWin people have done[0].

[0] https://projects.kde.org/projects/kde/kde-workspace/repository/revisions/6072b4feb8c90024aa24b2e9cb8a21ab2140412c

Well, I read the first link you provided, and the bottom part of the second (sorry, they are really too long!). I don't actually see anything particularly helpful. It provided a lot of workarounds/fixes on user side, but barely anything for us.

We actually borrowed the DRM VSync code from MythTV, and it isn't working too well, apparently. (RTC, BusyWait, and usleep methods aren't copied, I think they aren't designed for VSync at all...) DRI2 VSync is possible, but I couldn't find a Xlib binding for it, only a XCB binding is available, and chjj doesn't really like porting to XCB. I also looked at the fbcompose mentioned: It uses glXSwapBuffers() with the OpenGL backend, but with X Render backend I don't see it doing any VSync.

Oops, sorry, this is a bug. Reversing the order of the vsync_init() call and init_overlay() call will fix this. I will push it tomorrow.

Great; thanks. That combination did seem so far to have the best
effect in reducing tearing.

I've pushed the fix as 4bc3de8 to richardgv-dev branch on the git repo. The PPA probably won't be immediately updated, though.

For --paint-on-overlay, please read the "Composite Overlay Window" section of compositeproto.txt of Xorg: http://cgit.freedesktop.org/xorg/proto/compositeproto/tree/compositeproto.txt

Thanks -- that was enlightening. So, when you paint on the overlay
window (which I take just to be a special window on top of all the
others), as determined by this --paint-on-overlay switch, what do you
paint there that is different from before (ie, different from without
the switch)?

We paint exactly the same thing, at exactly the same moment, using exactly the same method. The difference is where we paint it: Not the root window now but the overlay window.

And by the way, I suspect xorg-server itself may internally just copy the content from the overlay window to root window, somehow.

Ok, great. Does this mean that --dbe entails double graphics memory use?

X exposes the interface/protocol, and we generally ignore the implementation details. If you really need to know, I believe the DBE implementation that comes with xorg-server-1.14.0, called MIDBE (Machine-Independent DBE), uses a X Pixmap as the backbuffer. Whether a X Pixmap resides in the memory or the video memory is probably driver-dependent and well beyond my knowledge.

Also, generally the root window uses a 24-bit visual, so a 1440x900 image is likely to take 4MB. Unless what you have is a 3dfx Voodoo or nVidia RIVA TNT2, this shouldn't be a big concern to you, I hope.

@M4he
M4he commented Mar 12, 2013

It has been years of struggling for me trying to get rid of tearing on Linux when using compositing.
Besides mutter (Gnome 3) and other DE-dependend compositors with some quirky workarounds the only solution left for me was dcompmgr (http://git.openbox.org/?p=dana/dcompmgr.git;a=summary) despite being old and having bugs.
Using "dcompmgr --gl" works flawlessly. It does use quite some CPU but I get rid of tearing completely (including videos; no top screen line whatsoever). No other standalone compositor manages to achieve this.

Compton with opengl vsync does a fine job on the desktop already but there are still things with tearing:

  1. videos (mplayer, regardless of which output driver is used)
  2. moving large images (i.e. large image in EOG to 1:1 scaling and moving the image within the window)
  3. smooth scrolling on webpages in firefox

I don't know what kind of magic is going on in dcompmgr but maybe compton could learn something from it?

I'm really grateful for what compton has achieved already! You did a good job.
Maybe one day it can finally be a replacement for dcompmgr on my system and get rid of tearing once and for all...

@richardgv
Collaborator

@M4he:

dcompmgr could eliminate tearing because it uses OpenGL as backend instead of X Render. X Render doesn't expose an interface that could be used for doing VSync properly. I'm trying to add an OpenGL backend, but give me some time, okay?

@M4he
M4he commented Mar 13, 2013

@richardgv Sorry I misinterpreted the OpenGL VSync switch as an OpenGL backend mode.
I'm glad you are planning to add a real OpenGL backend! I know this is not an easy task, so take your time.

Thanks for all your efforts!
Unfortunately, I can't help with coding as I lack the OpenGL and X Server knowledge but if I can help with anything else, just ask.

@richardgv richardgv added a commit that referenced this issue Mar 15, 2013
@richardgv richardgv Feature: OpenGL backend
- Add experimental OpenGL backend (--opengl). --blur-background is
  currently not possible with this backend, because I'm still trying to
  find a proper way to do blur with OpenGL. Flipping backend on-the-fly
  is really hard, so it isn't supported right now. No configuration file
  option exists to enable this, because it isn't stable enough.

- Add `opengl-swc` VSync method that uses SGI_swap_control to control
  buffer swap, with OpenGL backend. (#7)

- Fix a potential read-from-freed-memory issue in paint_all().

- Correctly reattach GLX context after fork.

- Dump error text in error(). Add GLX error code handling.

- Code clean-up.

- Known issues: Region operations take a lot of time in glx_render().
  I'm hesitating about what to do.
8ffcf1c
@richardgv
Collaborator

@M4he, @tsmithe, and people all the way above:

I've added an experimental OpenGL backend (8ffcf1c) to richardgv-dev branch, and a VSync method opengl-swc that uses SGI_swap_control -- the VSync methods all those OpenGL compositors use. More details in the commit log. I would like to hear how it works for you. The recommended configuration is:

compton --opengl --sw-opti --vsync opengl-swc --paint-on-overlay

Also, does anyone have some suggestions on improving the design of glx_render()? Profiling with callgrind shows all those XFixes region operations are taking quite some time. Are they worthwhile? OpenGL forces full-screen repaint (MESA_copy_sub_buffer isn't supported by nvidia-drivers, I believe?). Are there any workarounds?

@Janhouse

Not sure if I was supposed to try it but I did anyway.

00:02.0 VGA compatible controller: Intel Corporation 3rd Gen Core processor Graphics Controller (rev 09)

Didn't really work. Here is the screen:

2013-03-15-175101_1440x900_scrot

./compton --opengl --sw-opti --vsync opengl-swc --paint-on-overlay
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
Mesa 9.1 implementation error: bad target in _mesa_select_tex_object()
Please report at bugs.freedesktop.org
^C

@mkraemer

Same for me, also using intel graphics:

00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (rev 09)

While the output on my screen looks the same as the one of Janhouse (solid white windows on black background), a screenshot looks slighly different:

..

@richardgv
Collaborator

Huh, sorry. I'm using nvidia-drivers-313.26 personally and there's nothing wrong I could see. I will test it with VirtualBox tomorrow. It's midnight here now.

@mkraemer

No need to be sorry, the development speed of compton is awesome :D Thank you 👍

I will probably be able to test opengl mode with the amd catalyst driver at the weekend :)

@richardgv
Collaborator

Huh, no time to test myself now. Just a quick patch, to be applied on 8ffcf1c. Could any of you test if this works?

diff --git a/src/common.h b/src/common.h
index 30c09e3..6bd50eb 100644
--- a/src/common.h
+++ b/src/common.h
@@ -594,6 +594,8 @@ typedef struct {
   // === OpenGL related ===
   /// GLX context.
   GLXContext glx_context;
+  /// Whether we have GL_ARB_texture_non_power_of_two.
+  bool glx_has_texture_non_power_of_two;
   /// Pointer to glXGetVideoSyncSGI function.
   f_GetVideoSync glXGetVideoSyncSGI;
   /// Pointer to glXWaitVideoSyncSGI function.
diff --git a/src/compton.c b/src/compton.c
index f8c33d2..7e3cc4d 100644
--- a/src/compton.c
+++ b/src/compton.c
@@ -5709,6 +5709,7 @@ session_init(session_t *ps_old, int argc, char **argv) {

 #ifdef CONFIG_VSYNC_OPENGL
     .glx_context = None,
+    .glx_has_texture_non_power_of_two = false,
     .glXGetVideoSyncSGI = NULL,
     .glXWaitVideoSyncSGI = NULL,
     .glXGetSyncValuesOML = NULL,
diff --git a/src/opengl.c b/src/opengl.c
index 16e99de..8317a30 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -51,7 +51,7 @@ glx_init(session_t *ps, bool need_render) {
   }

   // Ensure GLX_EXT_texture_from_pixmap exists
-  if (need_render && !glx_hasext(ps, "GLX_EXT_texture_from_pixmap"))
+  if (need_render && !glx_hasglxext(ps, "GLX_EXT_texture_from_pixmap"))
     goto glx_init_end;

   // Get GLX context
@@ -68,6 +68,11 @@ glx_init(session_t *ps, bool need_render) {
     goto glx_init_end;
   }

+  // Check GL_ARB_texture_non_power_of_two
+  if (need_render)
+    ps->glx_has_texture_non_power_of_two = glx_hasglext(ps,
+        "GL_ARB_texture_non_power_of_two");
+
   // Acquire function addresses
   if (need_render) {
     ps->glXBindTexImageProc = (f_BindTexImageEXT)
@@ -350,11 +355,23 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
     printf_dbgf("(): depth %d rgba %d\n", depth, (GLX_TEXTURE_FORMAT_RGBA_EXT == pcfg->texture_fmt));
 #endif

-    int attrs[] = {
+    // Determine texture target, copied from compiz
+    GLint tex_tgt = 0;
+    if (GLX_TEXTURE_2D_BIT_EXT & pcfg->texture_tgts
+        && ps->glx_has_texture_non_power_of_two)
+      tex_tgt = GLX_TEXTURE_2D_EXT;
+    else if (GLX_TEXTURE_RECTANGLE_BIT_EXT & pcfg->texture_tgts)
+      tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
+    else if (!(GLX_TEXTURE_2D_BIT_EXT & pcfg->texture_tgts))
+      tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
+    else
+      tex_tgt = GLX_TEXTURE_2D_EXT;
+
+    GLint attrs[] = {
         GLX_TEXTURE_FORMAT_EXT,
         pcfg->texture_fmt,
-        // GLX_TEXTURE_TARGET_EXT,
-        // ,
+        GLX_TEXTURE_TARGET_EXT,
+        tex_tgt,
         0,
     };

diff --git a/src/opengl.h b/src/opengl.h
index b48b441..815b38a 100644
--- a/src/opengl.h
+++ b/src/opengl.h
@@ -13,23 +13,48 @@
 #include <ctype.h>

 /**
- * Check if a GLX extension exists.
+ * Check if a word is in string.
  */
 static inline bool
-glx_hasext(session_t *ps, const char *ext) {
-  const char *glx_exts = glXQueryExtensionsString(ps->dpy, ps->scr);
-  const char *pos = strstr(glx_exts, ext);
-  // Make sure the extension string is matched as a whole word
+wd_is_in_str(const char *haystick, const char *needle) {
+  if (!haystick)
+    return false;
+
+  const char *pos = strstr(haystick, needle);
   if (!pos
-      || ((pos - glx_exts) && !isspace(*(pos - 1)))
-      || (strlen(pos) > strlen(ext) && !isspace(pos[strlen(ext)]))) {
-    printf_errf("(): Missing OpenGL extension %s.", ext);
+      || ((pos - haystick) && !isspace(*(pos - 1)))
+      || (strlen(pos) > strlen(needle) && !isspace(pos[strlen(needle)]))) {
     return false;
   }
-
   return true;
 }

+/**
+ * Check if a GLX extension exists.
+ */
+static inline bool
+glx_hasglxext(session_t *ps, const char *ext) {
+  const char *glx_exts = glXQueryExtensionsString(ps->dpy, ps->scr);
+  bool found = wd_is_in_str(glx_exts, ext);
+  if (!found)
+    printf_errf("(): Missing GLX extension %s.", ext);
+
+  return found;
+}
+
+/**
+ * Check if a GLX extension exists.
+ */
+static inline bool
+glx_hasglext(session_t *ps, const char *ext) {
+  const char *gl_exts = (const char *) glGetString(GL_EXTENSIONS);
+  bool found = wd_is_in_str(gl_exts, ext);
+  if (!found)
+    printf_errf("(): Missing GL extension %s.", ext);
+
+  return found;
+}
+
 static inline XVisualInfo *
 get_visualinfo_from_visual(session_t *ps, Visual *visual) {
   XVisualInfo vreq = { .visualid = XVisualIDFromVisual(visual) };
@mkraemer

Seems to be working fine now on intel graphics :) THX

@Janhouse

I can confirm that the patch fixes it.
Also I noticed that fullscreen Youtube Flash videos do not lag anymore. Awesome, thank you! :)

@skry
skry commented Mar 15, 2013

I have 7600GT Nvidia card (304.64 driver). I briefly tested glxgears (steady 50fps, no tearing) and xbmc (ui, movie, all audio visualizers) and there's no tearing there either. Without the above patch glxgears slowed down a bit when fullscreen and motion wasn't smooth, with patch it's all ok. This is certainly a big improvement, I feel it's faster and I can't see tearing anywhere (well, except youtube fullscreen, couldn't care less) where it was noticeable before, or in general. Thanks.

@tsmithe
tsmithe commented Mar 15, 2013

Hi Richard,

adding to the clamour, that latest patch does indeed fix it very nicely for me, and I find I also do not need sw-opti or paint-on-overlay. This is with Intel Ivy Bridge graphics (xserver-xorg-video-intel 2:2.21.4+git20130312.4f8fba31-0ubuntu0sarvatt), Linux 3.7.0-10.dmz.2-liquorix-amd64, SNA accareleration, TearFree off, and SwapbuffersWait on.

Well done, and many thanks,

Toby

@tritonas00

GREAT WORK!

nvidia 9600 gt here. i used: compton --opengl --sw-opti --vsync opengl-swc --paint-on-overlay

no tearing in desktop, no tearing in videos, no tearing at the top of screen, overall no tearing xD

Thank you for your amazing work!

@tsmithe
tsmithe commented Mar 15, 2013

@richardgv -- I just docked back at home with my second monitor, and noticed that the opengl code doesn't seem to respond well to unexpected xrandr/screen layout changes, which I hadn't noticed as a problem before. It's early days, I know, so I'm not at all complaining (the simple solution is to restart the compositor). Thanks again.

@richardgv richardgv added a commit that referenced this issue Mar 16, 2013
@richardgv richardgv Bug fix: GLX backend incompatibility with mesa & others
- Fix a bug that glx_bind_pixmap() doesn't work with mesa drivers.
  Thanks to Janhouse and mkraemer for reporting. (#7)

- Use stencil buffer to attempt to eliminate potential double-paint
  issue in glx_render(). X Fixes doesn't guarantee the rectangles in a
  region do not overlap, and this may cause some regions to be painted
  twice, which would be a problem if we are painting transparent things.
  Now the target window must have a stencil buffer. Compiz uses its own
  region implementation to deal with this, but as a lightweight
  compositor we can't really do the same. It may have a positive or
  negative effort over performance. Callgrind result indicates basically
  no change in performance, but this may or may not be true.

- Correctly distinguish GL extensions and GLX extensions. Sorry. :-D

- Handle screen size. Thanks to tsmithe for reporting. (#7)

- Rename OpenGL backend to GLX backend, because, we might have a EGL
  backend someday.

- Add configuration file option `backend` to specify backend. Add
  `backend` to D-Bus `opts_get`.

- Add OpenGL shader compilation code, but currently unused.

- Minor adjustments.

- Known issue: Window content doesn't get updated in VirtualBox,
  probably because its OpenGL implementation requires constant rebinding
  of texture. But that's really slow...

- Known issue: Blur feature is still unimplemented in GLX backend.
66be1f2
@richardgv
Collaborator

Sorry, I'm doing things a bit slowly today. Saturdays and Sundays are always upset for me. :-) Anyway, the patch has been merged into richardgv-dev as 66be1f2.

There's a potential problem in the previous version: X Fixes doesn't guarantee the rectangles in a region don't overlap, and when we paint according to those rectangles we might paint a region twice. If the region is transparent, this will result in wrong opacity. (And in extreme cases, bad performance.) So far I've not noticed it actually happening, but to get things on the safe side I used stencil buffer to define painting region in a more correct way. The outcomes are:

  1. Now the target window must have a stencil buffer. I hope this isn't a problem for most modern hardware, though.
  2. It may have a positive or negative effect on performance. We may go back to the old design if severe performance problems are noticed.

Compiz use a whole region computation system to evade the problem, as far as I know, but we can't really do the same.

And, sorry for you, @Janhouse, background blur is still not available for GLX backend. It looks more tricky to implement than expected. glConvolutionFilter2D() looks okay but it's rumored that it isn't hardware-accelerated. I suspect glCopyPixels() isn't the correct way to read and blur the background, and I couldn't set raster position correctly somehow. Compiz uses the low-level ARB assembly language to do blurring, and it feels rather crazy to copy those stuffs... I may have to put this on hold unless I want to fail again in my exams.

And, I discovered under VirtualBox the window content doesn't get updated correctly under GLX backend. Looks like VirtualBox isn't quite binding the texture to pixmap in a perfect way. A possible solution is to rebind texture every time it's damaged just like what Compiz do, yet this may cause some performance penalty when a window is rapidly updating its content -- like glxgears. Still hesitating about what to do.

... Without the above patch glxgears slowed down a bit when fullscreen and motion wasn't smooth, with patch it's all ok. ...

Oh, I wasn't expecting that's related to performance.

... I can't see tearing anywhere (well, except youtube fullscreen, couldn't care less) ...

Hmm, I thought glXSwapIntervalSGI could eliminate all tearing... Do you see this problem with other OpenGL-based compositing managers, too?

@tsmithe:

I just docked back at home with my second monitor, and noticed that the opengl code doesn't seem to respond well to unexpected xrandr/screen layout changes, which I hadn't noticed as a problem before.

Yeah, this is a bug. I didn't test changing screen size. I hope 66be1f2 fixes the issue.

@skry
skry commented Mar 16, 2013

@richardgv

Well, slowing down a bit == 5fps but the movement was jerky. This might have had something to do with spectrwm, I noticed that when the top bar was hidden it was fine, and when visible, glxgears fps dropped and started puking. With patch glxgears was smooth regardless of the bar.

Regarding to flash video, I'll try to test it some more, it might be configuration issue too, though I think I've never got satisfactory fullscreen hd playback with adobe's abomination.

I've now used this build for a day and it feels stable. Worse I got was a few BadWindow errors, but I think I've seen those with other compositors / window managers before.

Edit: Not BadWindow, but BadDrawable and BadPixmap instead.

@richardgv
Collaborator

I just discovered various weird things about shadows under GLX backend. Still investigating...

I've now used this build for a day and it feels stable. Worse I got was a few BadWindow errors, but I think I've seen those with other compositors / window managers before.

Edit: Not BadWindow, but BadDrawable and BadPixmap instead.

Huh, they are probably normal, especially if you have fading enabled, as described in #52. You proably don't get BadWindow because it's slienced in some cases, while BadPixmap, etc., are not yet. Anyway, I think it isn't a big problem unless you could spot a visible defect on the screen.

@M4he
M4he commented Mar 17, 2013

Wow, that was quick!

Using compton --opengl --vsync opengl-swc --paint-on-overlay with a GTX 660 and driver 304.43 on a 1080p resolution.

Had to remove --sw-opti for mplayer to play 60 fps content more smoothly (otherwise would have to specify the double refresh rate of my display, which seems to work as well).
I'm glad that I'm able to disable this option! Compiz for instance doesn't provide this capability and can't display 60 fps vidoes smoothly either, leaving me with setting the double refresh rate which leads to other problems in compiz and is a total mess.

Regardless, it is amazing! So far no signs of tearing anywhere: desktop, videos, flash player.
And the performance is mindblowing too: dcompmgr & Xorg used 100% CPU of one core when a transparent terminal window was moved around; compton & Xorg only use about 30% (w/o --sw-opti)!

@richardgv this is the most awesome progress on the Linux desktop I've seen in the last time.
It has surpassed compiz now in terms of performance with 60 fps videos and is on par with mutter. Though the latter doesn't really count since mutter is bound to Gnome 3 (which crashes/freezes too often for me) and not standalone plus it requires some clutter workaround switches to eliminate tearing.
Therefore your current compton version is the best opengl compositor out there now, if it proves being stable.

I can't express my gratitude for your great work and efforts enough. Keep up the good work!

@richardgv
Collaborator

Had to remove --sw-opti for mplayer to play 60 fps content more smoothly (otherwise would have to specify the double refresh rate of my display, which seems to work as well).

To be honest, I personally never realize the difference between a FPS of 60 and 30. I sometimes use --refresh-rate 20 myself. :-)

I'm glad that I'm able to disable this option! Compiz for instance doesn't provide this capability and can't display 60 fps vidoes smoothly either, leaving me with setting the double refresh rate which leads to other problems in compiz and is a total mess.

Oh, sorry, I didn't know that. Doesn't Compiz have a "Sync To VBlank" option that could be turned off? Also, Compiz does have the feature to unredirect fullscreen windows, and Compiz-0.9.x (although rather broken on all distros except Ubuntu...) has the feature to unredirect arbitary windows, I remember, which should be enough to ensure perfect video playback.

And the performance is mindblowing too: dcompmgr & Xorg used 100% CPU of one core when a transparent terminal window was moved around; compton & Xorg only use about 30% (w/o --sw-opti)!

I'm using nvidia-drivers, too. Actually even with no compositor, when I'm rapidly moving a window, the CPU usage of X process could go to almost 40% here. With compton it goes up to 90%. (But --sw-opti lowers this down very effectively.) Profiling results from sysprof shows 86% of the CPU time are used in kernel space, 78% by "ioctl". It may not all be the fault in the compositor, but possibly the driver or something else. Well, I might need a special OpenGL profiler to figure out what's going on here. BuGLe looks terribly broken and apitrace couldn't do profiling in real-time thus isn't really applicable to a compositor, hmm...

this is the most awesome progress on the Linux desktop I've seen in the last time. It has surpassed compiz now in terms of performance with 60 fps videos and is on par with mutter.

Compiz has plenties of performance optimizations that we don't yet / can't do in compton: MESA_copy_sub_buffer support, custom region calculation implementation that eliminates the need to use the slower stencil buffer, and those fragment shaders written in ARB assembly language. To honest I don't think the performance of any a compositor could exceed Compiz. (It does use too much memory, though.) :-)

I can't express my gratitude for your great work and efforts enough. Keep up the good work!

Thanks! :-)

@M4he
M4he commented Mar 17, 2013
Doesn't Compiz have a "Sync To VBlank" option that could be turned off?

Yep it does but it introduces tearing if turned off, which is what I'm trying to get rid of after all.

The thing with Compiz is, I can't use Mplayer's xv or vdpau video output because it has horrible tearing (even with every VSync option enabled) and have to rely on the gl output of mplayer which tends to be less smooth for me.
Despite that I have other issues with Compiz as well: invisible menus, occasional black window contents etc.
I don't want to start a Compiz discussion here. Let's just say that the OpenGL backend of Compton does fit my needs far better than Compiz does and it's worth the 'loss' in performance for me.

I have been running Compton the whole day now and I only noticed 2 little things:

  1. when resizing windows (especially vertically) their contents jitter. Text looks like it's bouncing. Doesn't happen with dcompmgr.
  2. when a Flash video is visible on a webpage in Firefox, scrolling is very choppy. Could be the fault of Flash itself; it happens in dcompmgr too. Flash on Linux has always been a problem.
@richardgv
Collaborator

ARGB windows and shadows are painted darked than the correct color. I've found a fix and will push it tomorrow.

when resizing windows (especially vertically) their contents jitter. Text looks like it's bouncing. Doesn't happen with dcompmgr.

Thanks. It's reproducible. Looks like an issue in texture coordinate calculation. I will look into this tomorrow.

when a Flash video is visible on a webpage in Firefox, scrolling is very choppy. Could be the fault of Flash itself; it happens in dcompmgr too. Flash on Linux has always been a problem.

Reproducible, too, but I suspect it's tied with something in OpenGL, so, it's less likely to be fixed.

@richardgv
Collaborator

(In addition to what I said above...)

when resizing windows (especially vertically) their contents jitter. Text looks like it's bouncing. Doesn't happen with dcompmgr.

It's a timing issue. I don't have the time to explain what is happening right now. A quick & dirty fix that has some negative effect on performance, among other things

diff --git a/src/common.h b/src/common.h
index 77aa582..55b19e1 100644
--- a/src/common.h
+++ b/src/common.h
@@ -297,9 +297,9 @@ struct _glx_texture {
   GLuint texture;
   GLXPixmap glpixmap;
   Pixmap pixmap;
-  int width;
-  int height;
-  int depth;
+  unsigned width;
+  unsigned height;
+  unsigned depth;
   bool y_inverted;
 };
 #endif
@@ -1572,8 +1572,7 @@ bool
 glx_init_blur(session_t *ps);

 bool
-glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
-    int width, int height, int depth);
+glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap);

 void
 glx_release_pixmap(session_t *ps, glx_texture_t *ptex);
@@ -1686,3 +1685,39 @@ c2_match(session_t *ps, win *w, const c2_lptr_t *condlst,
 ///@}

 #endif
+
+/**
+ * @brief Dump raw bytes in HEX format.
+ *
+ * @param data pointer to raw data
+ * @param len length of data
+ */
+static inline void
+hexdump(const char *data, int len) {
+  static const int BYTE_PER_LN = 16;
+
+  if (len <= 0)
+    return;
+
+  // Print header
+  printf("%10s:", "Offset");
+  for (int i = 0; i < BYTE_PER_LN; ++i)
+    printf(" %2d", i);
+  putchar('\n');
+
+  // Dump content
+  for (int offset = 0; offset < len; ++offset) {
+    if (!(offset % BYTE_PER_LN))
+      printf("0x%08x:", offset);
+
+    printf(" %02hhx", data[offset]);
+
+    if ((BYTE_PER_LN - 1) == offset % BYTE_PER_LN)
+      putchar('\n');
+  }
+  if (len % BYTE_PER_LN)
+    putchar('\n');
+
+  fflush(stdout);
+}
+
diff --git a/src/compton.c b/src/compton.c
index 591fc70..c6fe1b6 100644
--- a/src/compton.c
+++ b/src/compton.c
@@ -474,6 +474,7 @@ win_build_shadow(session_t *ps, win *w, double opacity) {

   w->shadow_paint.pixmap = shadow_pixmap_argb;
   w->shadow_paint.pict = shadow_picture_argb;
+
   bool success = paint_bind_tex(ps, &w->shadow_paint, shadow_image->width, shadow_image->height, 32, true);

   XFreeGC(ps->dpy, gc);
@@ -863,8 +864,7 @@ get_root_tile(session_t *ps) {
   ps->root_tile_paint.pixmap = pixmap;
 #ifdef CONFIG_VSYNC_OPENGL
   if (BKEND_GLX == ps->o.backend)
-    return glx_bind_pixmap(ps, &ps->root_tile_paint.ptex, ps->root_tile_paint.pixmap,
-        ps->root_width, ps->root_height, ps->depth);
+    return glx_bind_pixmap(ps, &ps->root_tile_paint.ptex, ps->root_tile_paint.pixmap);
 #endif

   return true;
diff --git a/src/compton.h b/src/compton.h
index 9c4bd0a..2500282 100644
--- a/src/compton.h
+++ b/src/compton.h
@@ -185,7 +185,7 @@ paint_bind_tex(session_t *ps, paint_t *ppaint, int wid, int hei, int depth,
   // TODO: Make sure we have the same Pixmap binded?
   if (BKEND_GLX == ps->o.backend
       && (force || !glx_tex_binded(ppaint->ptex, ppaint->pixmap))) {
-    return glx_bind_pixmap(ps, &ppaint->ptex, ppaint->pixmap, wid, hei, depth);
+    return glx_bind_pixmap(ps, &ppaint->ptex, ppaint->pixmap);
   }
 #endif

diff --git a/src/opengl.c b/src/opengl.c
index b32368e..1b2cf86 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -107,7 +107,6 @@ glx_init(session_t *ps, bool need_render) {

     // glEnable(GL_DEPTH_TEST);
     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     glDisable(GL_BLEND);

     if (!ps->o.glx_no_stencil) {
@@ -321,19 +320,7 @@ glx_cmp_fbconfig(session_t *ps,
  * Bind a X pixmap to an OpenGL texture.
  */
 bool
-glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
-    int width, int height, int depth) {
-  if (depth > OPENGL_MAX_DEPTH) {
-    printf_errf("(%d): Requested depth higher than %d.", depth,
-        OPENGL_MAX_DEPTH);
-    return false;
-  }
-  const glx_fbconfig_t *pcfg = ps->glx_fbconfigs[depth];
-  if (!pcfg) {
-    printf_errf("(%d): Couldn't find FBConfig with requested depth.", depth);
-    return false;
-  }
-
+glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap) {
   const GLenum target = GL_TEXTURE_2D;
   glx_texture_t *ptex = *pptex;
   bool need_release = true;
@@ -359,8 +346,7 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
   glEnable(target);

   // Release pixmap if parameters are inconsistent
-  if (ptex->texture && !(width == ptex->width && height == ptex->height
-        && ptex->pixmap == pixmap && depth == ptex->depth)) {
+  if (ptex->texture && ptex->pixmap != pixmap) {
     glx_release_pixmap(ps, ptex);
   }

@@ -380,7 +366,6 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
     glBindTexture(target, 0);

     ptex->texture = texture;
-    ptex->y_inverted = pcfg->y_inverted;
   }
   if (!ptex->texture) {
     printf_errf("(): Failed to allocate texture.");
@@ -393,6 +378,29 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
   if (!ptex->glpixmap) {
     need_release = false;

+    // Retrieve pixmap parameters
+    {
+      Window rroot = None;
+      int rx = 0, ry = 0;
+      unsigned rbdwid = 0;
+      if (!XGetGeometry(ps->dpy, pixmap, &rroot, &rx, &ry,
+            &ptex->width, &ptex->height, &rbdwid, &ptex->depth)) {
+        printf_errf("(%#010lx): Failed to query Pixmap info.", pixmap);
+        return false;
+      }
+      if (ptex->depth > OPENGL_MAX_DEPTH) {
+        printf_errf("(%d): Requested depth higher than %d.", ptex->depth,
+            OPENGL_MAX_DEPTH);
+        return false;
+      }
+    }
+
+    const glx_fbconfig_t *pcfg = ps->glx_fbconfigs[ptex->depth];
+    if (!pcfg) {
+      printf_errf("(%d): Couldn't find FBConfig with requested depth.", ptex->depth);
+      return false;
+    }
+
     // Determine texture target, copied from compiz
     GLint tex_tgt = 0;
     if (GLX_TEXTURE_2D_BIT_EXT & pcfg->texture_tgts
@@ -406,7 +414,7 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
       tex_tgt = GLX_TEXTURE_2D_EXT;

 #ifdef DEBUG_GLX
-    printf_dbgf("(): depth %d, tgt %#x, rgba %d\n", depth, tex_tgt,
+    printf_dbgf("(): depth %d, tgt %#x, rgba %d\n", ptex->depth, tex_tgt,
         (GLX_TEXTURE_FORMAT_RGBA_EXT == pcfg->texture_fmt));
 #endif

@@ -419,6 +427,7 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
     };

     ptex->glpixmap = glXCreatePixmap(ps->dpy, pcfg->cfg, pixmap, attrs);
+    ptex->y_inverted = pcfg->y_inverted;
   }
   if (!ptex->glpixmap) {
     printf_errf("(): Failed to allocate GLX pixmap.");
@@ -436,9 +445,6 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, Pixmap pixmap,
   glBindTexture(target, 0);
   glDisable(target);

-  ptex->width = width;
-  ptex->height = height;
-  ptex->depth = depth;
   ptex->pixmap = pixmap;

   return true;
@@ -532,10 +538,14 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
   if (opacity < 1.0 || GLX_TEXTURE_FORMAT_RGBA_EXT ==
       ps->glx_fbconfigs[ptex->depth]->texture_fmt) {
     glEnable(GL_BLEND);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
     // Needed for handling opacity of ARGB texture
     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-    glColor4f(1.0f, 1.0f, 1.0f, opacity);
+
+    // This is all weird, but X Render is using a strange ARGB format, and
+    // we need to use those things to correct it. Thanks to derhass for help.
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+    glColor4f(opacity, opacity, opacity, opacity);
   }

   // Color negation
@richardgv richardgv added a commit that referenced this issue Mar 18, 2013
@richardgv richardgv Bug fix: GLX: ARGB texture too dark & Jitter when resize & others
- GLX backend: Fix a bug that ARGB windows / shadows are rendered too
  dark. Thanks to derhass in FreeNode/##opengl for help.

- GLX backend: Fix a problem that during window resize the content looks
  jittering, by letting compton fetch pixmap sizes with XGetGeometry()
  instead of relying on window width/height, which could be inaccurate
  during window resize. Negative effect on performance. Thanks to M4he
  for reporting. (#7)

- Add .desktop file. Thanks to quequotion for providing it. (#97)

- Avoid checking presence of window pixmap, because they may not exist
  with very old X Composite implementations.

- Add workaround for a strange window restack issue when compton
  receieves a ConfigureNotify with non-existent new above window.

- Add debugging function hexdump(). Extra sanity checks on various
  places.
1a88e3d
@richardgv
Collaborator

@M4he: I've merged the fix of the jitter issue (the patch above) to richardgv-dev branch as 1a88e3d. Thanks again! :-)

@bartcerneels

(I'm the colleague of Jeroen, involved in this thread in the past)

Using richardgv-dev commit 1a88e3d we get less then 0 improvement using the VIA chrome9.
compton --opengl --vsync opengl-swc has massive frame drops and even then there is still tearing.

Here is a snipped of glxinfo output that might be relevant:
name of display: :0
display: :0 screen: 0
direct rendering: Yes
server glx vendor string: SGI
server glx version string: 1.4
server glx extensions:
GLX_ARB_multisample, GLX_EXT_import_context, GLX_EXT_texture_from_pixmap,
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_MESA_copy_sub_buffer,
GLX_OML_swap_method, GLX_SGI_make_current_read, GLX_SGI_swap_control,
GLX_SGIS_multisample, GLX_SGIX_fbconfig, GLX_SGIX_pbuffer,
GLX_SGIX_visual_select_group, GLX_INTEL_swap_event
client glx vendor string: Mesa Project and SGI
client glx version string: 1.4
client glx extensions:
GLX_ARB_get_proc_address, GLX_ARB_multisample, GLX_EXT_import_context,
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_EXT_framebuffer_sRGB,
GLX_MESA_copy_sub_buffer, GLX_MESA_multithread_makecurrent,
GLX_MESA_swap_control, GLX_OML_swap_method, GLX_OML_sync_control,
GLX_SGI_make_current_read, GLX_SGI_swap_control, GLX_SGI_video_sync,
GLX_SGIS_multisample, GLX_SGIX_fbconfig, GLX_SGIX_pbuffer,
GLX_SGIX_visual_select_group, GLX_EXT_texture_from_pixmap,
GLX_INTEL_swap_event
GLX version: 1.4
GLX extensions:
GLX_ARB_get_proc_address, GLX_ARB_multisample, GLX_EXT_import_context,
GLX_EXT_visual_info, GLX_EXT_visual_rating, GLX_MESA_copy_sub_buffer,
GLX_MESA_multithread_makecurrent, GLX_MESA_swap_control,
GLX_OML_swap_method, GLX_OML_sync_control, GLX_SGI_make_current_read,
GLX_SGI_swap_control, GLX_SGI_video_sync, GLX_SGIS_multisample,
GLX_SGIX_fbconfig, GLX_SGIX_pbuffer, GLX_SGIX_visual_select_group,
GLX_EXT_texture_from_pixmap, GLX_INTEL_swap_event
OpenGL vendor string: VIA Technologies, Inc.
OpenGL renderer string: Gallium 0.4 on Chrome9
OpenGL version string: 1.4 Mesa 7.11 (git-8c70008)
OpenGL extensions:
GL_ARB_multisample, GL_EXT_abgr, GL_EXT_bgra, GL_EXT_blend_color,
GL_EXT_blend_logic_op, GL_EXT_blend_minmax, GL_EXT_blend_subtract,
GL_EXT_copy_texture, GL_EXT_polygon_offset, GL_EXT_subtexture,
GL_EXT_texture_object, GL_EXT_vertex_array, GL_EXT_compiled_vertex_array,
GL_EXT_texture, GL_EXT_texture3D, GL_IBM_rasterpos_clip,
GL_ARB_point_parameters, GL_EXT_draw_range_elements, GL_EXT_packed_pixels,
GL_EXT_point_parameters, GL_EXT_rescale_normal,
GL_EXT_separate_specular_color, GL_EXT_texture_edge_clamp,
GL_SGIS_generate_mipmap, GL_SGIS_texture_border_clamp,
GL_SGIS_texture_edge_clamp, GL_SGIS_texture_lod, GL_ARB_multitexture,
GL_IBM_multimode_draw_arrays, GL_IBM_texture_mirrored_repeat,
GL_ARB_texture_cube_map, GL_ARB_texture_env_add, GL_ARB_transpose_matrix,
GL_EXT_blend_func_separate, GL_EXT_fog_coord, GL_EXT_multi_draw_arrays,
GL_EXT_secondary_color, GL_EXT_texture_env_add,
GL_EXT_texture_filter_anisotropic, GL_EXT_texture_lod_bias,
GL_INGR_blend_func_separate, GL_NV_blend_square, GL_NV_light_max_exponent,
GL_NV_texgen_reflection, GL_NV_texture_env_combine4,
GL_SUN_multi_draw_arrays, GL_ARB_texture_border_clamp,
GL_ARB_texture_compression, GL_EXT_framebuffer_object,
GL_EXT_texture_env_dot3, GL_MESA_window_pos, GL_NV_packed_depth_stencil,
GL_NV_texture_rectangle, GL_ARB_depth_texture, GL_ARB_shadow,
GL_ARB_texture_env_combine, GL_ARB_texture_env_crossbar,
GL_ARB_texture_env_dot3, GL_ARB_texture_mirrored_repeat,
GL_ARB_window_pos, GL_EXT_stencil_two_side, GL_EXT_texture_cube_map,
GL_APPLE_packed_pixels, GL_APPLE_vertex_array_object, GL_ARB_draw_buffers,
GL_ARB_fragment_program, GL_ARB_vertex_program, GL_ATI_draw_buffers,
GL_ATI_texture_env_combine3, GL_EXT_shadow_funcs, GL_EXT_stencil_wrap,
GL_MESA_pack_invert, GL_MESA_ycbcr_texture,
GL_ARB_fragment_program_shadow, GL_ARB_half_float_pixel,
GL_ARB_point_sprite, GL_ARB_sync, GL_ARB_texture_non_power_of_two,
GL_ARB_vertex_buffer_object, GL_ATI_blend_equation_separate,
GL_EXT_blend_equation_separate, GL_OES_read_format,
GL_ARB_pixel_buffer_object, GL_ARB_texture_rectangle,
GL_EXT_pixel_buffer_object, GL_EXT_texture_rectangle,
GL_ARB_framebuffer_object, GL_EXT_framebuffer_blit,
GL_EXT_framebuffer_multisample, GL_EXT_packed_depth_stencil,
GL_ARB_vertex_array_object, GL_ATI_separate_stencil,
GL_EXT_gpu_program_parameters, GL_EXT_texture_env_combine,
GL_OES_EGL_image, GL_ARB_copy_buffer, GL_ARB_map_buffer_range,
GL_ARB_vertex_array_bgra, GL_EXT_vertex_array_bgra,
GL_ARB_ES2_compatibility, GL_ARB_draw_elements_base_vertex,
GL_ARB_fragment_coord_conventions, GL_ARB_provoking_vertex,
GL_ARB_sampler_objects, GL_EXT_provoking_vertex, GL_ARB_robustness

@bartcerneels

No improvement with --vsync opengl-oml

@richardgv
Collaborator

Using richardgv-dev commit 1a88e3d we get less then 0 improvement using the VIA chrome9.
compton --opengl --vsync opengl-swc has massive frame drops and even then there is still tearing.

Hey hey hey, there's a few things I would like to tell you before you continue your harsh comments:

  1. I never told you that should try OpenGL backend on such broken chips and drivers. OpenGL backend cannot be reliable if the driver isn't. For whatever happens on the less-reliable VIA drivers I cannot be responsible.
  2. OpenGL backend is experimental right now. It is currently not and will never be the default backend of compton.
  3. 1a88e3d is not the latest version.
  4. Compton is free. You payed not a cent to me. I'm afraid hearing you speaking like you are my employer is not going to make me feel particularly well, and I don't think this is beneficial if you actually want to solve a problem, either.

compton --opengl --vsync opengl-swc has massive frame drops and even then there is still tearing.

Until you could provide more details on what exactly is happening -- at least tell me if you get frame drops without the vsync option! --- or show me another OpenGL compositor / VSync method that works perfectly on your driver, I'm afraid what I could do is pretty limited.

No improvement with --vsync opengl-oml

Others have reported opengl-oml/opengl-swc are effective, and I did absolutely no special treatment on VIA chips. It's more likely a problem in the implementation of OML_sync_control in the VIA instead of a problem here.

@bartcerneels

1a88e3d is not the latest version.

I know, you pushed that while I was testing. Pulled and rebased and can confirm that doesn't change anything. Not that I expected it would. The benchmark feature is a nice addition, thanks.

Compton is free. You payed not a cent to me. I'm afraid hearing you speaking like you are my employer is not going to make me feel particularly well, and I don't think this is beneficial if you actually want to solve a problem.

I understand how you feel. Even though I'm getting payed for what I'm doing right now I've got plenty of floss project experience. I'll proofread with my unpayed-floss-contributor glasses on next time. Email/comments are terrible at delivering tone after all, better to be clear and unambiguous.
In the meanwhile I'll do my best to help you debug this so the opengl backend can be improved for all.

Others have reported opengl-oml is effective, and I did absolutely no special treatment on VIA chips. It's more likely a problem in the implementation of OML_sync_control in the VIA instead of a problem here.

That is most likely. I'll dig deeper.

@richardgv
Collaborator

@bartcerneels:

In the meanwhile I'll do my best to help you debug this so the opengl backend can be improved for all.

Thanks for helping, then. :-)

Email/comments are terrible at delivering tone after all, better to be clear and unambiguous.

Indeed. More than once I have been criticized for appearing rude, although I'm trying hard to use the polite words. :-D

  1. I have no VIA hardware at hand. Well, I basically have nothing except a GTX 670 and Virtualbox. There's no way for me to test the VIA things myself.

  2. The thing that would help me the most is showing me an example of a working OpenGL compositor on your machine/driver with a better VSync so that I could clone its implementation. You are welcome to provide patches to improve this, as well. cairo-compmgr and dcompmgr both use SGI_swap_control for VSync, Compiz and mutter probably do. If they work correctly, most likely I have something wrong in my code. If they don't work either... Guess the only thing I could do is to send a mail to VIA asking them to improve the driver.

  3. Do you actually get frame dropping with no options other than --backend glx? You could try compton --config /dev/null --backend glx. If there's no frame dropping in this case, could you please try figuring out which option is causing the issue?

  4. compton has a few related options to play with: --paint-on-overlay, --glx-no-stencil, --glx-copy-from-front (see compton -h for help). Maybe you could play with different combinations to see if they change anything?

  5. --benchmark will cause compton to paint continuously, and you could calculate the FPS with it, with help from /usr/bin/time. Getting FPS from a GL debugger (like gDebugger) is possible as well, although I found gDebugger giving quite some loss in performance (over 50% here). Would you mind showing me the normal FPS? A FPS close to or lower than your refresh rate could be a dangerous thing for VSync. And, do you see a 100% CPU usage (which means, bottleneck on CPU) or lower (bottleneck on GPU, I think?) when running in benchmark mode?

  6. Do you see the problem related to the number of visible windows on your screen and things that are costly to draw (shadows, ARGB content, transparent things)?

  7. Does compton print out any warnings or errors?

  8. I'm not completely sure if the choice of OpenGL FBConfig are related to the performance. Compile compton with -DDEBUG_GLX in CFLAGS, and you could see compton dumping how it chooses the FBConfig. (Make sure you use a pipe when capturing compton. -DDEBUG_GLX dumps a huge amount of things.) The lines should resemble:

    glx_update_fbconfig_bydepth(24): 0x107 overrides 0, target 0x20df.
    glx_update_fbconfig_bydepth(32): 0x107 overrides 0, target 0x20df.
    glx_update_fbconfig_bydepth(24): 0x10b overrides 0x107, target 0x20df.
    glx_update_fbconfig_bydepth(32): 0x10b overrides 0x107, target 0x20df.
    glx_update_fbconfig_bydepth(24): 0x113 overrides 0x10b, target 0x20df.
    glx_update_fbconfig_bydepth(32): 0x113 overrides 0x10b, target 0x20df.
    glx_update_fbconfig_bydepth(24): 0x11b overrides 0x113, target 0x20df.
    glx_update_fbconfig_bydepth(32): 0x11b overrides 0x113, target 0x20df.
    

    If you think they are related, you could post this part and the visual / FBConfig part of glxinfo output. You could also hack glx_update_fbconfig_bydepth() so that it accepts a specific FBConfig only, and test the possible FBConfigs one by one. (A lot of work!)

  9. If you find abnormally high CPU usage, please check if you could get anything from profiling results.

  10. Does opengl-oml and other VSync methods work better or worse for XRender backend? For VSync methods based on waiting (drm, opengl, opengl-oml), you could compile compton with -DDEBUG_REPAINT in CFLAGS (you could search in the replies above for the usage) and check if the interval of painting is abnormally high because of VSync. Well, if that's really happening it should affect XRender backend as well.

  11. I see GLX_MESA_copy_sub_buffer is supported with your driver. If VirtualBox supports that extension as well maybe I could later use it to improvement performance in some degree -- but this will not be helpful for full-screen content updates, like movie playback. I'm not sure if VSync still works properly with it, though.

  12. It's close to midnight, I have no energy to think further. :-D

This was referenced Mar 28, 2013
@M4he
M4he commented Sep 15, 2013

I've been using compton --opengl --vsync opengl-swc --paint-on-overlay for a long time now and never had any serious problems. It runs just great! Thanks again for the hard work!

I recently switched to mplayer's OpenGL video output instead of XV. I noticed that when moving the mplayer window or moving another window above mplayer, the window movement becomes very laggy while a video is playing. (also happens with VLC's OpenGL output)
Is this a limitation of the current GLX backend implementation?

@richardgv
Collaborator

@M4he:

I recently switched to mplayer's OpenGL video output instead of XV. I noticed that when moving the mplayer window or moving another window above mplayer, the window movement becomes very laggy while a video is playing. (also happens with VLC's OpenGL output)
Is this a limitation of the current GLX backend implementation?

I couldn't reproduce it here with GTX 650, compton (git-v0.1_beta1-12-g747ffae-2013-09-15) (exactly the same arguments), media-video/vlc-2.0.7 (OpenGL GLX video output), media-video/mpv-0.1.6 (fork of mplayer2, -vo=opengl), indicating this issue is probably somehow related to your system or driver. (It's laggy when my CPU is completely used, though.)

There are a few possibilities. One of them is compton and your video player is exhausting some sort of resources. Due to certain design decisions in compton (trading higher CPU usage during window position/size changes for low GPU and CPU usage in other cases), compton uses quite a lot of CPU during interactive window movement. You could drop some resource-hogging options (e.g. --blur-background). And you could check your CPU usage, GPU usage (with nvidia-smi, etc.), GPU fan speed (reflects GPU usage), memory usage, etc. The performance optimization options of compton (rating limiting ones like --sw-opti, --vsync drm, --vsync opengl, --vsync opengl-oml, and other ones like --glx-no-stencil, --glx-use-copysubbuffermesa, --glx-swap-method, --glx-no-rebind-pixmap) may help.

Another possibility is your SGI_swap_control implementation is mishaving. You could try to drop the VSync option, use another VSync method, or check your driver configuration for implicit VSync (nvidia-settings, .drirc, xorg.conf).

And last but not least, you may try other video outputs (vdpau, vaapi, x11) to see if they bring any lucks.

@M4he
M4he commented Sep 16, 2013

@richardgv:

Thanks for your quick and elaborated answer!
I'm using a GTX 660 with driver 325.15 on openbox standalone.
I now disabled Sync to VBlank in nvidia-settings as it doesn't seem to be needed at all. That didn't change anything at first. Then I replaced --vsync opengl-swc with --vsync opengl and normal videos (around 30fps) don't produce any lagging anymore. Additionally Flash videos in Firefox don't slow down the scrolling anymore.
The odd thing is, 60fps videos work fine at first as well. But after a short time playing, any 60fps video produces heavy window movement lags even though normal videos are still unaffected. I need to kill and restart compton several times to get rid of that but it happens again after playing any 60fps video for a short time.
Very odd. The only "fancy" feature of compton I'm using is shadows (no blur or fade etc.). I've tried turning that off, leaving an empty compton.conf file but that didn't change anything.

Here's a free 60fps video if you want to try reproducing it: http://www.nostro.fr/AMV/Nostromo_-_Distant_Echo_720p@60_8b.mp4

For comparison I tested on an Intel HD 4000 with mplayer -vo=gl and compton: No lagging, not even with 60fps videos. Neither with --vsync opengl-swc nor with --vsync opengl. This setup runs perfect.

@richardgv
Collaborator

@M4he:

I now disabled Sync to VBlank in nvidia-settings as it doesn't seem to be needed at all. That didn't change anything at first. Then I replaced --vsync opengl-swc with --vsync opengl and normal videos (around 30fps) don't produce any lagging anymore. Additionally Flash videos in Firefox don't slow down the scrolling anymore.
The odd thing is, 60fps videos work fine at first as well. But after a short time playing, any 60fps video produces heavy window movement lags even though normal videos are still unaffected. I need to kill and restart compton several times to get rid of that but it happens again after playing any 60fps video for a short time.
Very odd. The only "fancy" feature of compton I'm using is shadows (no blur or fade etc.). I've tried turning that off, leaving an empty compton.conf file but that didn't change anything.

  1. One possibility is compton or something compton calls is slowly leaking resources. If the slowdown issue doesn't occur without --vsync (actually the changes after switching to --vsync=opengl already somehow confirms this), we could mostly exclude the possibility. (Although, the VSync code may leak things, but then the issue is more likely on the driver side.) Typically phenomenons are high CPU usage on X / compton process or high GPU / memory usage.
  2. Another possibility is some sort of delay is gradually accumulating... I have no idea why it would occur. Unless you see high CPU/GPU usage, the issue is more possibly in the driver.
  3. Is the delay longer than 1/60 second?

Here's a free 60fps video if you want to try reproducing it: http://www.nostro.fr/AMV/Nostromo_-_Distant_Echo_720p@60_8b.mp4

160MB! I will test it when I'm back home.

And my recommendations are still: Play with your driver settings (nvidia-settings, .drirc, xorg.conf), and try other video outputs (vdpau, vaapi, x11).

@M4he
M4he commented Sep 21, 2013

So, I did some very thorough testing: https://docs.google.com/spreadsheet/ccc?key=0AjhHjzQIZ8LjdDBDU1ZNemJUQ2daUVRFaG00M1BBT0E&usp=sharing
For reference here's my xorg.conf: http://pastebin.com/tS8xCLFm

Although --vsync opengl seemed to do the trick at first, it occasionally shows tearing at the upper screen edge. According to the test results, there seems to be no noticeable difference between compton's opengl-swc VSync and nvidia's VSync.
XV output is a no-go because of its random micro-stutter during playback. GL has issues with 60fps and window movement.
VDPAU seems to be the best choice. Window movement is not entirely smooth but it has no major drawbacks.

The Intel HD 4000 runs perfectly no matter the setting (everything is smooth; much less Xorg cpu load).

@M4he
M4he commented Sep 21, 2013

Okay, VDPAU isn't a choice either.
When mplayer is playing through VDPAU on openbox's workspace 1 and I switch from workspace 1 to workspace 2 and back, the screen and mplayer freezes. I can get the screen back if I attempt to switch workspaces a few times again (using keyboard) but mplayer stays frozen while only displaying the part of the wallpaper below and needs to be killed.
Now I'm back to square one...

@richardgv
Collaborator

@M4he:

Ah, sorry, I entirely forgot this issue after I got home...

When X starts occupying 100% of a core, disasters will generally start to appear. I would recommend a system-wide profiling in the case to figure out what's wrong.

Flash is a true nightmare. And you may consider it normal to see delay when you scroll a page with Flash -- it typically uses much of your CPU.

I will see what I could do about shadow generation to reduce the cost of window resizing (note, I do not know if it works for moving).

@M4he
M4he commented Sep 22, 2013

@richardgv:

You don't need to. Even if I drop the shadow option everything behaves the same.
I also tried booting without any xorg.conf - no luck.

I think the problem is, that the GL and compositing synchronization of the nvidia drivers is a complete joke.
For testing I just replaced my nvidia drivers with the intel ones, plugged in my screen at the mainboard and switched to the Intel HD 2500 integrated in my cpu: compton --opengl --paint-on-overlay without any additional options (no VSync option!): everything is so super smooth, no tearing, no lag not even the slightest. Moving mplayer window (vo=gl) with 60fps video: X uses 10% cpu (compare 90 - 100% on nvidia using vo=gl). This is the kind of performance one would expect from modern hardware - the intel chips makes it feel like it's 10 times better than my GTX 660 lol.
Too bad it's such a hassle to reconnect the plug everytime and set the bios option to switch cards.

If I wouldn't need the card on Windows this would be the point where I'd sell it together with my current cpu and get the HD 4000 version of the core i5.

@richardgv
Collaborator

@M4he:

Let's say that nvidia-drivers performed almost perfectly on GTX 670 (home computer) and GTX 650 (work computer) in my experiences. Performance is superb, the library is stable (unless I write some broken code...), X acceleration is reliable (check the shit in nouveau!), supported GL version is much higher than the open-source ones, power saving is decent (I once burnt my Geforce 8800 GT because of nouveau). If there's anything I could complain, it's lack of KMS support (no wayland & slow to switch between virtual consoles and X) and being closed-source (so it's tricky to debug inside libGL). The fact that I hardly watch videos may affect my impressions, though, but nvidia-drivers never depressed me when I do -- no tearing have I ever seen. (And I've heard far more reports of tearing with Intel chipsets than nVidia cards.)

I found a bit surprising that nvidia-driver-325.15 seemingly causes X to use 100% CPU usage when moving a mpv window with -vo=opengl, because I noticed no lagging whatsoever (well, thus I never thought it happens on my computer!). Further analysis revealed it's probably not entirely true that the CPU is "occupied". System-wide profiling shows delay_tsc and certain other functions in nvidia-drivers are using most of the CPU, but they are supposed to the idling/waiting functions. The output of sar, dstat, and top indicates the CPU is not actually occupied (almost always more than 90% idle) even when conky and pidstat show extreme CPU usage of the X process. I don't know much about how the kernel and CPU works, but I guess the issue perhaps not in how nvidia-drivers occupies CPU, but how it incorrectly synchronizes a compositor and an OpenGL application. (Another evidence is, glxgears running a 60Hz is extremely laggy to move here as well, but my system is capable to paint more than 35,000 frames per second when VSync in driver is turned off. Heh, then why moving a mpv -vo=opengl window here doesn't lag?)

By the way, I tried improving GLX shadow texture generation, but it perhaps performed badly since glTexImage2D() looks very slow on nvidia-drivers-325.15.

@M4he
M4he commented Sep 22, 2013

I just tried out mpv 0.1.7 with -vo=opengl but it behaves just the same as mplayer.
And yea, moving the glxgears window does lag as heavy as a 60fps video played in mplayer/mpv with GL output, though it's showing fps values around 60 (using nvidia's VSync and compton without any --vsync option).
When using compton's --vsync opengl-swc without nvidia's vsync however, glxgears window movement doesn't lag as much and glxgears produces much higher fps (~23,000). Without VSync/compositing, glxgears reaches around 30,000.

By the way, is compton's refresh rate locked to 60fps somehow? I recall setting compiz to 120 once because it performed smoother than with 60 during window movement.

@richardgv
Collaborator

@M4he:

Today I reproduced exactly what you reported: It happens here when either "Sync to VBlank" is turned on in nvidia-settings or I used --vsync opengl-swc. --vsync=opengl does limit painting to 60Hz according to --benchmark results but does not cause the issue. A 60 FPS video makes this more severe. Only one point is different: I see tearing in no cases. I have not the slightest idea why during all my previous tests I've never noticed the lagging... How did you manage to affect my computer? :-D

I started using sysbench --test=cpu --num-threads=8 --cpu-max-prime=50000 to measure the occupied CPU percentage. I use compton-git-v0.1_beta1-14-g4bd3db2-2013-09-18 with compton.sample.conf and -b --logpath /tmp/compton.log --backend glx --paint-on-overlay --blur-background --glx-no-stencil --glx-no-rebind-pixmap. "Sync To VBlank" turned on in nvidia-settings. My experiments:

  1. The normal result is around 10.8 seconds;
  2. A paused mpv window alone doesn't bring much changes, with -vo=vdpau or -vo=opengl.
  3. Moving a gVim window around very fast: 11.05s.
  4. Moving a paused mpv window with -vo=vdpau: 11.7s. No lag in video playback or window movement.
  5. A mpv window with -vo=vdpau playing a 1080P movie (resized pretty small): 11.5s, No issue;
  6. Moving a mpv window with -vo=vdpau playing the movie: 12.9s, No issue;
  7. Moving a paused mpv window with -vo=opengl: 11.7s, no issue.
  8. A mpv window with -vo=opengl playing the movie: 11.47s, no issue;
  9. Moving a mpv window with -vo=opengl playing the movie: 12.75s, lag in window movement. Killing sysbench doesn't bring noticeable changes.

Conclusion: It only slows down when both compton and mpv are updating window content with OpenGL. It performs well when all CPUs are completely occupied. There's no evidence indicating -vo=opengl is more CPU-hogging or the CPU usage lead to to the lag whatsoever.

When I dig into the source code of mpv and vlc I discovered a thing: They both try to call glXSwapInterval() for VSync as well. So I patched their sources to disable it:

(Although it says mpv-0.1.6, the patch does work for 0.1.7.)

--- mpv-0.1.6/video/out/vo_opengl.c~    2013-09-14 04:03:30.000000000 +0800
+++ mpv-0.1.6/video/out/vo_opengl.c 2013-09-23 23:06:27.979974201 +0800
@@ -316,9 +316,6 @@

     mpgl_set_context(p->glctx);

-    if (p->gl->SwapInterval)
-        p->gl->SwapInterval(p->swap_interval);
-
     p->renderer = gl_video_init(p->gl, vo->log);
     gl_video_set_output_depth(p->renderer, p->glctx->depth_r, p->glctx->depth_g,
                               p->glctx->depth_b);
--- vlc-2.0.7/modules/video_output/xcb/glx.c~   2013-09-23 23:19:59.789972521 +0800
+++ vlc-2.0.7/modules/video_output/xcb/glx.c    2013-09-23 23:20:05.779972509 +0800
@@ -369,25 +369,6 @@

     const char *glx_extensions = glXQueryExtensionsString (dpy, snum);

-    bool is_swap_interval_set = false;
-#ifdef GLX_SGI_swap_control
-    if (HasExtension (glx_extensions, "GLX_SGI_swap_control")) {
-        PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)GetProcAddress (NULL, "glXSwapIntervalSGI");
-        if (!is_swap_interval_set && SwapIntervalSGI)
-            is_swap_interval_set = !SwapIntervalSGI (1);
-    }
-#endif
-#ifdef GLX_EXT_swap_control
-    if (HasExtension (glx_extensions, "GLX_EXT_swap_control")) {
-        PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)GetProcAddress (NULL, "glXSwapIntervalEXT");
-        if (!is_swap_interval_set && SwapIntervalEXT)
-        {
-            SwapIntervalEXT (dpy, sys->glwin, 1);
-            is_swap_interval_set = true;
-        }
-    }
-#endif
-
     /* Initialize common OpenGL video display */
     sys->gl.lock = NULL;
     sys->gl.unlock = NULL;

Then, the problem is gone, at least here, if I disable "Sync To VBlank" in nvidia-drivers but use --vsync=opengl-swc on compton. I have no idea if it would cause tearing on your side, though.

So, probably nvidia-drivers doesn't like a compositor using SGI_swap_control working with a client using SGI_swap_control as well, and handled the synchronization improperly. You may forward the info to the nVidia guys, to see if they could do anything.

By the way, is compton's refresh rate locked to 60fps somehow? I recall setting compiz to 120 once because it performed smoother than with 60 during window movement.

Unless you have VSync set in drivers or --vsync or --sw-opti, compton paints whenever there's a demand, as fast as 4370 full-screen repaints per second here. How much frames compton actively paints per second could be measured with the method describes in Performance guide. However even though compton paints that much a second, when and which frames are sent to video card and to the 60Hz screen is beyond our control, and the GPU may be processing less frames.

@richardgv
Collaborator

@M4he:

(In addition to the things above...)

You may wish to check if applying this patch on compton is useful, if patching mpv and vlc doesn't help:

diff --git a/src/compton.c b/src/compton.c
index 511083c..9bd4f87 100644
--- a/src/compton.c
+++ b/src/compton.c
@@ -1890,12 +1890,6 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
     // Make sure all previous requests are processed to achieve best
     // effect
     XSync(ps->dpy, False);
-#ifdef CONFIG_VSYNC_OPENGL
-    if (ps->glx_context) {
-      glFlush();
-      glXWaitX();
-    }
-#endif
   }

   // Wait for VBlank. We could do it aggressively (send the painting
@@ -1941,13 +1935,6 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t

   XFlush(ps->dpy);

-#ifdef CONFIG_VSYNC_OPENGL
-  if (ps->glx_context) {
-    glFlush();
-    glXWaitX();
-  }
-#endif
-
   XFixesDestroyRegion(ps->dpy, region);

 #ifdef DEBUG_REPAINT

Turn off VSync in nvidia-settings but enable it with --vsync opengl-swc may produce the best result.

@M4he
M4he commented Sep 24, 2013

@richardgv:

Thank you very much for your thorough research and detailed explanations!
I just tested the patched mpv together with compton --opengl --vsync opengl-swc --paint-on-overlay and "Sync to VBlank" turned off in nvidia-settings. I'll still need to conduct further testing when I get back home but from what I've just tested this patch seems to be the salvation! I spotted no tearing or lagging whatsoever playing various 720p and 1080p stuff including 60fps content.

  1. If this proves to be the solution I'll make sure to contact nvidia regarding the SWI_swap_control like you suggested!
  2. Does removing above lines in the code of said players have any drawbacks? I didn't spot anything bad even without any compositor running during some quick tests.
  3. Related to (2.), would it be of any use to contact the devs of said players regarding this?

When I get back, I'll test the patched mpv on Gnome as well and see if it solves the lagging there too while retaining vsync.

Once again, thanks for all your efforts and the hard work!
I take my hat off to you, you really know your stuff.

@richardgv
Collaborator

@M4he:

If this proves to be the solution I'll make sure to contact nvidia regarding the SWI_swap_control like you suggested!

I would recommend to try patching compton with the the patch in my last reply, to check if it has something to do with my usage of glXWaitX() . Within my current tests it has no effect (I guess I got the wrong result a few hours back because your test video made me feel dizzy... :-D ).

Does removing above lines in the code of said players have any drawbacks? I didn't spot anything bad even without any compositor running during some quick tests.

Huh, I don't know. Theoretically it may lead to certain frames being dropped if the timing is inappropriate.

Related to (2.), would it be of any use to contact the devs of said players regarding this?

They can and should provide an option to switch VSync on/off, although I doubt if they would care about this.

@antcodd
antcodd commented Sep 24, 2013

@richardgv

I also find that vsync on in more than one place of compton/mpv/nvidia tends to cause lots of frame stuttering. This is even with 23.976 fps video at 47.952Hz.

They can and should provide an option to switch VSync on/off, although I doubt if they would care about this.

Note that mpv vo=opengl/opengl-hq has a swapinterval=<n> option which should disable all vsync when set to 0. I find this gets rid of most of the juddering, especially when compton is in opengl-swc mode.

You may wish to check if applying this patch on compton is useful, if patching mpv and vlc doesn't help

I think this patch might be helping a little but it is really hard to tell. The trouble is with vsync off mpv is probably essentially 'freewheeling' so stuttering issues can occur when the first frame start is at an odd point in the refresh cycle. This tends to happen for me every 5-10 seeks and significantly moreso with swapinterval=1.

I notice with compton off, swapinterval=1 (default) in mpv I get tearing only on my second monitor (the 1080p one), contradictory to what nvidia-settings says is the monitor it is vsyncing to. So long as the composite extension is enabled (which I can't disable without hacking gnome-session despite not using gnome shell and obviously can't use compton with) I can't find any combination of vsync settings in nvidia or mpv to make it work. Amazingly compton in opengl/opengl-swc seems to be the one thing that correctly vsyncs on both monitors!

By the way does compton properly support multiple monitors and changing refresh rates? I have a script that automatically changes refresh rate of my second monitor with xrandr to a multiple of the video refresh rate before playback starts. I think it is working but it's hard to tell with the intermittent stuttering problems.

It would be fantastic to get this issue resolved one way or another and finally have stutter and tear free video output. Vsync is such a nightmare on Linux!

@richardgv
Collaborator

@antcodd:

Note that mpv vo=opengl/opengl-hq has a swapinterval=<n> option which should disable all vsync when set to 0. I find this gets rid of most of the juddering, especially when compton is in opengl-swc mode.

Aha! Apparently it was a bad idea to work at midnight. I should have noticed it.

I think this patch might be helping a little but it is really hard to tell.

So it means my call to glXWaitX() is not the cause, then. Good news!

The trouble is with vsync off mpv is probably essentially 'freewheeling' so stuttering issues can occur when the first frame start is at an odd point in the refresh cycle. This tends to happen for me every 5-10 seeks and significantly moreso with swapinterval=1.

Eee... It could happen theoretically but I've never seen it, and I didn't realize it would be that severe. Unfortunately, I doubt if I could do anything about it. It might be possible to patch mpv to use an alternative VSync method (e.g. SGI_video_sync), though.

I notice with compton off, swapinterval=1 (default) in mpv I get tearing only on my second monitor (the 1080p one), contradictory to what nvidia-settings says is the monitor it is vsyncing to. ... Amazingly compton in opengl/opengl-swc seems to be the one thing that correctly vsyncs on both monitors!

No idea why that would happen.

By the way does compton properly support multiple monitors and changing refresh rates? I have a script that automatically changes refresh rate of my second monitor with xrandr to a multiple of the video refresh rate before playback starts. I think it is working but it's hard to tell with the intermittent stuttering problems.

Compton does not detect refresh rate for VSync itself but relies on the OpenGL VSync extensions. Whether they handle refresh rate changes correctly is up to the driver. (Compton does detect refresh rate for --sw-opti, though.) Many are using compton with multiple monitors.

@richardgv
Collaborator

@antcodd:

(In addition to the previous reply...)

I wrote a patch to add SGI_video_sync to mpv, as a replacement for SGI_swap_control. It does not disable SGI_swap_control automatically. Weirdly enough, I could no longer reproduce the issue after turning "Sync To VBlank" off in nvidia-settings anyhow, even with --vsync opengl-swc.

@M4he
M4he commented Sep 24, 2013

I wrote a patch to add SGI_video_sync to mpv, as a replacement for SGI_swap_control. It does not disable SGI_swap_control automatically.

So I need to apply both this patch and the one you posted earlier?

@richardgv
Collaborator

@M4he:

So I need to apply both this patch and the one you posted earlier?

The new SGI_video_sync patch is intended to fix the stuttering issue antcodd reported when he has SGI_swap_control in mpv disabled. Unless you experience the same problem, the patch would not be necessary.

By the way, as mpv has an option swapinterval=<n> to control if SGI_swap_control is enabled, pointed out by antcodd, my previous patch on mpv is not needed, either.

@antcodd
antcodd commented Sep 25, 2013

@richardgv

Thanks for the SGI_video_sync patch

After some more investigation I've discovered problems only tend to occur when both monitors are on, and only on the second monitor (regardless of how I set primary in xrandr I believe). The first monitor vsyncs the same as if there was a single monitor on.

On my second monitor having both swapinterval=1 and --opengl-swc does pretty much exactly the same jittering as when I apply your patch and forget to set swapinterval=0. Your patch seems to jitter for me even when compton is off, and with a single monitor, and even with swapinterval=0 so I suspect it is a little buggy in its interaction with the rest of mpv (don't think it's really worth worrying about).

I've discovered the composite extension makes no difference for me either - the critical thing is that vsync only ever happens on my first monitor if it is on. Without compton with every combination I've seen I see two tear lines (one at each 3rd of the screen) on the second monitor. With compton --opengl-swc I get vsync on both screens but juddering when vsync is on in more than one place, and occasional frame skips/jumps (less often than I remember yesterday for some reason) if I set swapinterval=0 in normal mpv. I'm pretty sure refresh rate switching is working correctly with compton.

Sometimes I think there is some micro-stuttering (delayed frames or something), but it is hard to tell with 24p video. I'm not yet convinced whether it is my imagination, or in what situations it happens though. It could easily be causee by the lack of Reclock-like functionality in mpv to sync the clocking.

For now I guess I'll just modify my script to turn off the first monitor. I'm still interested in solving this issue. I suspect it is a bug in the NVIDIA driver. It is also possible either mpv or NVIDIA is causing the vsync call blocking to be timed to the other monitor or something (two tearing lines makes me suspicious of something strange happening). One monitor is using DVI and the one I'm trying to use is HDMI by the way (HDMI-0 has it's own entry in xorg.conf with custom modelines, the other one that gets vsynced to is auto configured).

Hope that is intelligible, I got myself rather confused at one point.

@richardgv
Collaborator

@antcodd:

Does the methods here help for you? https://wiki.archlinux.org/index.php/NVIDIA#Vertical_sync_using_TwinView

Well, I guess I can't solve your issue. It looks so complicated and it's impossible for me to reproduce it here. (I don't have a second monitor.) Maybe you could contact nVidia directly. And NVIDIA Developer Forums and nV News might be good places to ask your questions.

You are definitely not alone. Some people suggested disabling composite extension as a solution. Eeek!
https://devtalk.nvidia.com/default/topic/540730/again-tearing-problems-with-drivers-gt-300-dual-head-setup/
https://devtalk.nvidia.com/default/topic/540113/linux/video-tears-on-all-screens

My SGI_video_sync patch is intended to be used with swapinterval=0. Applying double VSync most likely will cause troubles. Adding glFlush() and glXWaitX() before VSync might be helpful, but not too likely.

I suppose that probably you overestimated the importance of mpv in this process. As a video player, mpv should not and does not care about refresh rate, as far as I know. I believe its timing is based on video/audio frames, and it calls select() to wait for next frame and other inputs, which has nothing to do with GPU. Look around line 2700, run_playloop(), in mpv-0.1.7/mpvcore/mplayer.c for more details. VSync is to be done by the driver. A video player along cannot know where the VBlank is or wait for VBlank accurately without the driver, and it's only a matter of how mpv cooperates with it.

Are you using separate screens, XRandR, TwinView, or Xinerama? I heard they perform differently for VSync.

You have tried vdpau and other video outputs (x11, xv, sdl, etc.), haven't you? nvidia-settings has a VSync option for xv.

And switching to nouveau might be your last bet. Keep an eye on the temperature of your GPU, though.

@M4he
M4he commented Nov 11, 2013

Sorry for bringing this to attention once again but did anyone ever figure out what is the cause of the player/desktop freezes when switching workspaces back and forth while playing a video via vdpau?
(Compton's GLX backend, any player with vdpau - reproduced on openbox and xfce so far, didn't test others yet)

@richardgv
Collaborator

@M4he:

Sorry for bringing this to attention once again but did anyone ever figure out what is the cause of the player/desktop freezes when switching workspaces back and forth while playing a video via vdpau?

  1. VLC has gotten VDPAU support since 2.1.0. Does it exhibit the same problem?
  2. If it occurs on both media players, does it happen on other OpenGL compositors? (Compiz, Kwin) Or is it associated with compton, or a particular compton settings?
  3. If it happens on other compositors as well, you may wish to report this to nVidia.
  4. Using gdb (or a profiling tool, if it's inside a complicated infinite loop?) to break into the compton, X, or video player process and acquire backtraces may provide valuable hints on what is happening.
@M4he
M4he commented Nov 12, 2013

Just tried out VLC 2.1.1 using vlc --avcodec-hw=any. (I've read that this parameter forces the usage of VDPAU)

So if vlc's output

libva info: VA-API version 0.34.0
libva info: va_getDriverName() returns 0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/nvidia_drv_video.so
libva info: Found init function __vaDriverInit_0_32
libva info: va_openDriver() returns 0
[0x7f4484c60ec8] avcodec decoder: Using VA API version 0.34 for hardware decoding.

means that it is using VDPAU, then no - it doesn't happen with VLC.

@richardgv
Collaborator

@M4he:

Firstly, I'm truly sorry that there is one thing I didn't notice: mpv uses the rendering component of vdpau (VdpOutputSurface) but VLC probably only uses the decoder of vdpau, so... Most likely it isn't the same thing.

Your output seemingly indicates you are using VAAPI. I got the following output when VDPAU is enabled:

[0x7f8268c0dd18] avcodec decoder: Using NVIDIA VDPAU Driver Shared Library  331.20  Wed Oct 30 17:39:35 PDT 2013 for hardware decoding.
[0x7f8268c0dd18] avcodec decoder: Using NVIDIA VDPAU Driver Shared Library  331.20  Wed Oct 30 17:39:35 PDT 2013 for hardware decoding.

I enabled VDPAU support from VLC Preferences -> Codecs -> Hardware-accelerated decoding (Simple view) / Input/Codecs -> Video codecs -> FFmpeg -> Hardware decoding (all view).

@richardgv
Collaborator

ali1234 came with the interesting idea of using X Render for compositing and GLX for the last step of rendering content to screen, and I've implemented it in richardgv-dev branch (fbd70e1). It keeps all the performance weaknesses of X Render backend (slow color inversion and background blur), but it has the same level of VSync GLX backend provides. If for some reason GLX backend is unusable for you (like, sickening driver issues), but you need its VSync, --backend xr_glx_hybird might be useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment