Merge lp:~vanvugt/compiz-core/fix-880707 into lp:compiz-core/0.9.5

Proposed by Daniel van Vugt
Status: Superseded
Proposed branch: lp:~vanvugt/compiz-core/fix-880707
Merge into: lp:compiz-core/0.9.5
Diff against target: 145 lines (+11/-59)
2 files modified
plugins/composite/src/screen.cpp (+7/-8)
plugins/opengl/src/screen.cpp (+4/-51)
To merge this branch: bzr merge lp:~vanvugt/compiz-core/fix-880707
Reviewer Review Type Date Requested Status
Sam Spilsbury Approve
Review via email: mp+81737@code.launchpad.net

Description of the change

Reduced screen tearing still visible with "Sync To VBlank" enabled. (LP: #880707)

The composite plugin's frame timing logic did not correctly synchronize with the vblank support of other plugins (opengl). This would lead to excessive visible tearing even when "Sync To VBlank" is enabled in opengl.

This fix does NOT claim to eliminate all tearing, but it does eliminate most of it. To completely eliminate tearing more work has to be done to make the glXSwapBuffers code (opengl plugin) fast enough to use on every frame.

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I suspect this will fix bug 92599 too, so long as "Sync To VBlank" is enabled in OpenGL. Because composite will now ignore the rubbish framerate it gets from NVIDIA-Xrandr and will always use the natural refresh rate of the monitor instead.

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Hi Daniel,

Just to clarify, this returns to using glXWaitVideoSync and glXGetVideoSync rather than glXSwapInterval?

As for moving to using glXSwapBuffers - I agree with that, however the plugins generally expect that the damaged regions are going to be the ones copied over on to the frontbuffer from the backbuffer, rather than the entire back-to-front copy. Our current paint system allows for sort of "spill overs" on to the backbuffer, a much larger work item here is to make every plugin set its paint clipping region explicitly for each thing that it paints, so that the backbuffer is "sacred".

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Returning back to WaitVideoSync was necessary, because SwapInterval doesn't block. And we need the blocking in WaitVideoSync for accurate frame timing and to always stay in sync with the monitor. Composite's reasoning that it can magically stay in sync with the monitor's vsync with artificial timer delays was very misguided. If you have Sync to VBlank enabled then the only blocking should be the call to WaitVideoSync. This solves the problem of compiz painting out of phase, and even slightly out of frequency.

SwapInterval was originally used to try and "unblock the CPU". However I now realize that the main CPU blocking issue was this one -- bad timing in composite. SwapInterval made little to no difference and can be safely removed.

The critical fix for bug 763005 is still present:
  (*GL::waitVideoSync) (1, 0, &frameno);

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Tearing is further reduced by combining this proposal with another:
https://code.launchpad.net/~vanvugt/compiz-core/fix-priority/+merge/81952

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Work in progress again. I think I can improve on this significantly.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'plugins/composite/src/screen.cpp'
--- plugins/composite/src/screen.cpp 2011-10-15 11:00:51 +0000
+++ plugins/composite/src/screen.cpp 2011-11-09 14:27:01 +0000
@@ -706,7 +706,7 @@
706 (FPSLimiterMode == CompositeFPSLimiterModeVSyncLike ||706 (FPSLimiterMode == CompositeFPSLimiterModeVSyncLike ||
707 (pHnd && pHnd->hasVSync ()));707 (pHnd && pHnd->hasVSync ()));
708708
709 if (idle || hasVSyncBehavior)709 if (idle)
710 {710 {
711 if (timeMult > 1)711 if (timeMult > 1)
712 {712 {
@@ -715,6 +715,11 @@
715 timeMult--;715 timeMult--;
716 }716 }
717 }717 }
718 else if (hasVSyncBehavior)
719 {
720 frameStatus = 0;
721 redrawTime = diff;
722 }
718 else723 else
719 {724 {
720 int next;725 int next;
@@ -755,13 +760,7 @@
755 }760 }
756 }761 }
757 762
758 if (diff >= redrawTime)763 return (diff >= redrawTime) ? 1 : redrawTime - diff;
759 return 1;
760
761 if (hasVSyncBehavior)
762 return (redrawTime - diff) * 0.7;
763
764 return redrawTime - diff;
765}764}
766765
767int766int
768767
=== modified file 'plugins/opengl/src/screen.cpp'
--- plugins/opengl/src/screen.cpp 2011-10-26 23:15:02 +0000
+++ plugins/opengl/src/screen.cpp 2011-11-09 14:27:01 +0000
@@ -31,9 +31,6 @@
31#include <math.h>31#include <math.h>
3232
33namespace GL {33namespace GL {
34 typedef int (*GLXSwapIntervalProc) (int interval);
35
36 GLXSwapIntervalProc swapInterval = NULL;
37 GLXBindTexImageProc bindTexImage = NULL;34 GLXBindTexImageProc bindTexImage = NULL;
38 GLXReleaseTexImageProc releaseTexImage = NULL;35 GLXReleaseTexImageProc releaseTexImage = NULL;
39 GLXQueryDrawableProc queryDrawable = NULL;36 GLXQueryDrawableProc queryDrawable = NULL;
@@ -413,12 +410,6 @@
413 getProcAddress ("glXWaitVideoSyncSGI");410 getProcAddress ("glXWaitVideoSyncSGI");
414 }411 }
415412
416 if (strstr (glxExtensions, "GLX_SGI_swap_control"))
417 {
418 GL::swapInterval = (GL::GLXSwapIntervalProc)
419 getProcAddress ("glXSwapIntervalSGI");
420 }
421
422 fbConfigs = (*GL::getFBConfigs) (dpy, s->screenNum (), &nElements);413 fbConfigs = (*GL::getFBConfigs) (dpy, s->screenNum (), &nElements);
423414
424 for (i = 0; i <= MAX_DEPTH; i++)415 for (i = 0; i <= MAX_DEPTH; i++)
@@ -1076,44 +1067,18 @@
1076 priv->lastViewport.height);1067 priv->lastViewport.height);
1077}1068}
10781069
1079namespace GL
1080{
1081
1082void1070void
1083waitForVideoSync ()1071PrivateGLScreen::waitForVideoSync ()
1084{1072{
1073 // Docs: http://www.opengl.org/registry/specs/SGI/video_sync.txt
1085 if (GL::waitVideoSync)1074 if (GL::waitVideoSync)
1086 {1075 {
1087 // Don't wait twice. Just in case.
1088 if (GL::swapInterval)
1089 (*GL::swapInterval) (0);
1090
1091 // Docs: http://www.opengl.org/registry/specs/SGI/video_sync.txt
1092 unsigned int frameno;1076 unsigned int frameno;
1093 (*GL::waitVideoSync) (1, 0, &frameno);1077 (*GL::waitVideoSync) (1, 0, &frameno);
1094 }1078 }
1095}1079}
10961080
1097void1081void
1098controlSwapVideoSync (bool sync)
1099{
1100 // Docs: http://www.opengl.org/registry/specs/SGI/swap_control.txt
1101 if (GL::swapInterval)
1102 (*GL::swapInterval) (sync ? 1 : 0);
1103 else if (sync)
1104 waitForVideoSync ();
1105}
1106
1107} // namespace GL
1108
1109void
1110PrivateGLScreen::waitForVideoSync ()
1111{
1112 if (optionGetSyncToVblank ())
1113 GL::waitForVideoSync ();
1114}
1115
1116void
1117PrivateGLScreen::paintOutputs (CompOutput::ptrList &outputs,1082PrivateGLScreen::paintOutputs (CompOutput::ptrList &outputs,
1118 unsigned int mask,1083 unsigned int mask,
1119 const CompRegion &region)1084 const CompRegion &region)
@@ -1183,22 +1148,11 @@
1183 targetOutput = &screen->outputDevs ()[0];1148 targetOutput = &screen->outputDevs ()[0];
11841149
1185 glFlush ();1150 glFlush ();
1151 if (optionGetSyncToVblank ())
1152 waitForVideoSync ();
11861153
1187 /*
1188 * FIXME: Actually fix the composite plugin to be more efficient;
1189 * If GL::swapInterval == NULL && GL::waitVideoSync != NULL then the
1190 * composite plugin should not be imposing any framerate restriction
1191 * (ie. blocking the CPU) at all. Because the framerate will be controlled
1192 * and optimized here:
1193 */
1194 if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)1154 if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
1195 {1155 {
1196 /*
1197 * controlSwapVideoSync is much faster than waitForVideoSync because
1198 * it won't block the CPU. The waiting is offloaded to the GPU.
1199 * Unfortunately it only works with glXSwapBuffers in most drivers.
1200 */
1201 GL::controlSwapVideoSync (optionGetSyncToVblank ());
1202 glXSwapBuffers (screen->dpy (), cScreen->output ());1156 glXSwapBuffers (screen->dpy (), cScreen->output ());
1203 }1157 }
1204 else1158 else
@@ -1206,7 +1160,6 @@
1206 BoxPtr pBox;1160 BoxPtr pBox;
1207 int nBox, y;1161 int nBox, y;
12081162
1209 waitForVideoSync ();
1210 pBox = const_cast <Region> (tmpRegion.handle ())->rects;1163 pBox = const_cast <Region> (tmpRegion.handle ())->rects;
1211 nBox = const_cast <Region> (tmpRegion.handle ())->numRects;1164 nBox = const_cast <Region> (tmpRegion.handle ())->numRects;
12121165

Subscribers

People subscribed via source and target branches