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

Proposed by Daniel van Vugt
Status: Merged
Merged at revision: 2804
Proposed branch: lp:~vanvugt/compiz-core/fix-763005
Merge into: lp:compiz-core/0.9.5
Diff against target: 164 lines (+48/-18)
3 files modified
plugins/opengl/include/opengl/opengl.h (+4/-2)
plugins/opengl/src/privates.h (+1/-0)
plugins/opengl/src/screen.cpp (+43/-16)
To merge this branch: bzr merge lp:~vanvugt/compiz-core/fix-763005
Reviewer Review Type Date Requested Status
Sam Spilsbury Approve
compiz packagers Pending
Review via email: mp+73625@code.launchpad.net

This proposal supersedes a proposal from 2011-08-12.

Description of the change

Fix slow/stuttering display when Sync To VBlank is enabled. (LP: #763005)

For fglrx the cause appears to be an ATI/AMD driver bug where glXGetVideoSyncSGI and glXWaitVideoSyncSGI are particularly slow, so we can't afford to call both on every redraw or we end up with 1/3-1/2 framerate. For intel and really all drivers, another cause appears to be excessive waiting in the compiz architecture not allowing enough CPU time to draw the full frame before the next vertical refresh.

This proposal addresses both possible problems, providing optimal framerates with sync-to-vblank support, most of the time.

To post a comment you must log in.
Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote : Posted in a previous version of this proposal

Sam, can you look at this? Thanks!

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Sorry I got to this so late.

This looks good. Could you possibly retarget this against lp:compiz-core and make sure comments are on a new line ?

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

Modified comment style as requested and retargeted to lp:compiz-core.

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

Approve as per our discussion last time

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/opengl/include/opengl/opengl.h'
2--- plugins/opengl/include/opengl/opengl.h 2011-02-24 07:52:09 +0000
3+++ plugins/opengl/include/opengl/opengl.h 2011-09-01 03:50:21 +0000
4@@ -98,11 +98,13 @@
5 int width,
6 int height);
7
8- typedef int (*GLXGetVideoSyncProc) (unsigned int *count);
9 typedef int (*GLXWaitVideoSyncProc) (int divisor,
10 int remainder,
11 unsigned int *count);
12
13+ // http://www.opengl.org/registry/specs/SGI/swap_control.txt
14+ typedef int (*GLXSwapIntervalProc) (int interval);
15+
16 #ifndef GLX_VERSION_1_3
17 typedef struct __GLXFBConfigRec *GLXFBConfig;
18 #endif
19@@ -163,8 +165,8 @@
20 extern GLXReleaseTexImageProc releaseTexImage;
21 extern GLXQueryDrawableProc queryDrawable;
22 extern GLXCopySubBufferProc copySubBuffer;
23- extern GLXGetVideoSyncProc getVideoSync;
24 extern GLXWaitVideoSyncProc waitVideoSync;
25+ extern GLXSwapIntervalProc swapInterval;
26 extern GLXGetFBConfigsProc getFBConfigs;
27 extern GLXGetFBConfigAttribProc getFBConfigAttrib;
28 extern GLXCreatePixmapProc createPixmap;
29
30=== modified file 'plugins/opengl/src/privates.h'
31--- plugins/opengl/src/privates.h 2009-03-16 09:18:16 +0000
32+++ plugins/opengl/src/privates.h 2011-09-01 03:50:21 +0000
33@@ -70,6 +70,7 @@
34
35 void prepareDrawing ();
36
37+ void controlSwapVideoSync ();
38 void waitForVideoSync ();
39
40 void paintBackground (const CompRegion &region,
41
42=== modified file 'plugins/opengl/src/screen.cpp'
43--- plugins/opengl/src/screen.cpp 2011-02-24 07:52:09 +0000
44+++ plugins/opengl/src/screen.cpp 2011-09-01 03:50:21 +0000
45@@ -35,8 +35,8 @@
46 GLXReleaseTexImageProc releaseTexImage = NULL;
47 GLXQueryDrawableProc queryDrawable = NULL;
48 GLXCopySubBufferProc copySubBuffer = NULL;
49- GLXGetVideoSyncProc getVideoSync = NULL;
50 GLXWaitVideoSyncProc waitVideoSync = NULL;
51+ GLXSwapIntervalProc swapInterval = NULL;
52 GLXGetFBConfigsProc getFBConfigs = NULL;
53 GLXGetFBConfigAttribProc getFBConfigAttrib = NULL;
54 GLXCreatePixmapProc createPixmap = NULL;
55@@ -217,13 +217,16 @@
56
57 if (strstr (glxExtensions, "GLX_SGI_video_sync"))
58 {
59- GL::getVideoSync = (GL::GLXGetVideoSyncProc)
60- getProcAddress ("glXGetVideoSyncSGI");
61-
62 GL::waitVideoSync = (GL::GLXWaitVideoSyncProc)
63 getProcAddress ("glXWaitVideoSyncSGI");
64 }
65
66+ if (strstr (glxExtensions, "GLX_SGI_swap_control"))
67+ {
68+ GL::swapInterval = (GL::GLXSwapIntervalProc)
69+ getProcAddress ("glXSwapIntervalSGI");
70+ }
71+
72 glXMakeCurrent (dpy, CompositeScreen::get (s)->output (), priv->ctx);
73
74 glExtensions = (const char *) glGetString (GL_EXTENSIONS);
75@@ -986,19 +989,28 @@
76 }
77
78 void
79+PrivateGLScreen::controlSwapVideoSync ()
80+{
81+ bool sync = optionGetSyncToVblank ();
82+ // Docs: http://www.opengl.org/registry/specs/SGI/swap_control.txt
83+ if (GL::swapInterval)
84+ (*GL::swapInterval) (sync ? 1 : 0);
85+ else if (sync)
86+ waitForVideoSync ();
87+}
88+
89+void
90 PrivateGLScreen::waitForVideoSync ()
91 {
92- unsigned int sync;
93-
94- if (!optionGetSyncToVblank ())
95- return;
96-
97- if (GL::getVideoSync)
98+ if (optionGetSyncToVblank () && GL::waitVideoSync)
99 {
100- glFlush ();
101+ // Don't wait twice. Just in case.
102+ if (GL::swapInterval)
103+ (*GL::swapInterval) (0);
104
105- (*GL::getVideoSync) (&sync);
106- (*GL::waitVideoSync) (2, (sync + 1) % 2, &sync);
107+ // Docs: http://www.opengl.org/registry/specs/SGI/video_sync.txt
108+ unsigned int frameno;
109+ (*GL::waitVideoSync) (1, 0, &frameno);
110 }
111 }
112
113@@ -1071,10 +1083,23 @@
114
115 targetOutput = &screen->outputDevs ()[0];
116
117- waitForVideoSync ();
118+ glFlush ();
119
120+ //
121+ // FIXME: Actually fix the composite plugin to be more efficient;
122+ // If GL::swapInterval == NULL && GL::waitVideoSync != NULL then the
123+ // composite plugin should not be imposing any framerate restriction
124+ // (ie. blocking the CPU) at all. Because the framerate will be controlled
125+ // and optimized here:
126+ //
127 if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
128 {
129+ //
130+ // controlSwapVideoSync is much faster than waitForVideoSync because
131+ // it won't block the CPU. The waiting is offloaded to the GPU.
132+ // Unfortunately it only works with glXSwapBuffers in most drivers.
133+ //
134+ controlSwapVideoSync ();
135 glXSwapBuffers (screen->dpy (), cScreen->output ());
136 }
137 else
138@@ -1082,6 +1107,7 @@
139 BoxPtr pBox;
140 int nBox, y;
141
142+ waitForVideoSync ();
143 pBox = const_cast <Region> (tmpRegion.handle ())->rects;
144 nBox = const_cast <Region> (tmpRegion.handle ())->numRects;
145
146@@ -1137,7 +1163,7 @@
147 bool
148 PrivateGLScreen::hasVSync ()
149 {
150- return (GL::getVideoSync && optionGetSyncToVblank ());
151+ return (GL::waitVideoSync && optionGetSyncToVblank ());
152 }
153
154 void
155@@ -1145,7 +1171,8 @@
156 {
157 if (pendingCommands)
158 {
159- glFinish ();
160+ // glFlush! glFinish would block the CPU, which is bad.
161+ glFlush ();
162 pendingCommands = false;
163 }
164 }

Subscribers

People subscribed via source and target branches