Merge lp:~compiz-team/compiz/compiz.fix_1051286 into lp:compiz/0.9.8

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1051286
Merge into: lp:compiz/0.9.8
Diff against target: 1477 lines (+1021/-106)
15 files modified
plugins/opengl/CMakeLists.txt (+3/-0)
plugins/opengl/include/opengl/doublebuffer.h (+10/-1)
plugins/opengl/src/doublebuffer/CMakeLists.txt (+1/-0)
plugins/opengl/src/doublebuffer/src/double-buffer.cpp (+64/-11)
plugins/opengl/src/doublebuffer/tests/test-opengl-double-buffer.cpp (+166/-4)
plugins/opengl/src/privates.h (+24/-10)
plugins/opengl/src/screen.cpp (+107/-80)
plugins/opengl/src/vsyncmethod.h (+61/-0)
plugins/opengl/src/vsyncmethod/CMakeLists.txt (+25/-0)
plugins/opengl/src/vsyncmethod/include/vsync-method-swap-interval.h (+67/-0)
plugins/opengl/src/vsyncmethod/include/vsync-method-wait-video-sync.h (+67/-0)
plugins/opengl/src/vsyncmethod/src/vsync-method-swap-interval.cpp (+100/-0)
plugins/opengl/src/vsyncmethod/src/vsync-method-wait-video-sync.cpp (+87/-0)
plugins/opengl/src/vsyncmethod/tests/CMakeLists.txt (+24/-0)
plugins/opengl/src/vsyncmethod/tests/test-opengl-vsync-methods.cpp (+215/-0)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1051286
Reviewer Review Type Date Requested Status
Sam Spilsbury Needs Resubmitting
Daniel van Vugt Needs Resubmitting
jenkins (community) continuous-integration Needs Fixing
Review via email: mp+125838@code.launchpad.net

This proposal supersedes a proposal from 2012-09-19.

This proposal has been superseded by a proposal from 2012-09-28.

Commit message

Refactored the vsync code to get it under test. DoubleBuffer now dispatches to two separate VSync strategies depending on what type of swap we are doing. It also makes the unthrottledFrames code a lot clearer by specifying that this is for detecting broken hardware framelimiting.

Description of the change

This was originally going to be "deliver a big performance win on nvidia", however it seems like the local code where I had curtailed our use of glXSwapIntervalEXT delivering a performance boost is not reproducing the same conditions anymore.

Nevertheless, calling into opengGL redundantly is bad. And perhaps it is a condition on some hardware or other circumstances.

The main point of this branch is now as follows:

Refactored the vsync code to get it under test. DoubleBuffer now dispatches to two separate VSync strategies depending on what type of swap we are doing. It also makes the unthrottledFrames code a lot clearer by specifying that this is for detecting broken hardware framelimiting.

Take it or leave it I guess.

To post a comment you must log in.
Revision history for this message
jenkins (martin-mrazik+qa) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Forgive me for deferring this till after we branch (which should be very soon), if there is no good reason (any more) to risk a 1477 line diff in 0.9.8.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Please resubmit after we branch.

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

As above. Resubmitted locally to get CI to run again.

review: Needs Resubmitting
Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Resubmit after branching...

review: Needs Resubmitting
Revision history for this message
Martin Mrazik (mrazik) wrote :

This is the jenkins error:
pplying patch ccp_plugin.patch
patching file src/main.cpp
Hunk #1 succeeded at 147 (offset 1 line).

Applying patch workaround_broken_drivers.patch
patching file plugins/opengl/src/screen.cpp
Hunk #1 succeeded at 43 (offset 6 lines).
Hunk #2 FAILED at 289.
Hunk #3 succeeded at 913 (offset 84 lines).
1 out of 3 hunks FAILED -- rejects in file plugins/opengl/src/screen.cpp
Patch workaround_broken_drivers.patch does not apply (enforce with -f)
dh_quilt_patch: quilt --quiltrc /dev/null push -a || test $? = 2 returned exit code 1

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

Hmm, then again, bug 1051286 sounds important :/

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

I can't reproduce the condition in that bug anymore, so this can wait.

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

Set to WIP as there will be conflicts

review: Needs Resubmitting
3387. By Sam Spilsbury

Merge lp:compiz

Unmerged revisions

3387. By Sam Spilsbury

Merge lp:compiz

3386. By Sam Spilsbury

Put the bind pixmap handler after the double buffer handler so that the
latter can use it indirectly

3385. By Sam Spilsbury

Merge lp:compiz

3384. By Sam Spilsbury

Implement the vsync code in terms of the newer refactored code

3383. By Sam Spilsbury

Move the vsync hook into DoubleBuffer::render

3382. By Sam Spilsbury

Make all the tests pass - the logic is now implemented and just
needs to be hooked up

3381. By Sam Spilsbury

Refactored the double buffer classes somewhat to take a list of vsync
methods, test for their usage as appropriate

3380. By Sam Spilsbury

Added some unit tests, make them pass

3379. By Sam Spilsbury

Added test fixture from the video sync strategies code

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'plugins/opengl/CMakeLists.txt'
--- plugins/opengl/CMakeLists.txt 2012-09-17 13:48:33 +0000
+++ plugins/opengl/CMakeLists.txt 2012-09-22 03:12:18 +0000
@@ -6,13 +6,16 @@
6 compiz_opengl_double_buffer6 compiz_opengl_double_buffer
7 compiz_opengl_fsregion7 compiz_opengl_fsregion
8 compiz_opengl_glx_tfp_bind8 compiz_opengl_glx_tfp_bind
9 compiz_opengl_vsync_methods
9)10)
1011
11add_subdirectory (src/doublebuffer)12add_subdirectory (src/doublebuffer)
12add_subdirectory (src/fsregion)13add_subdirectory (src/fsregion)
13add_subdirectory (src/glxtfpbind)14add_subdirectory (src/glxtfpbind)
15add_subdirectory (src/vsyncmethod)
1416
15include_directories (src/glxtfpbind/include)17include_directories (src/glxtfpbind/include)
18include_directories (src/vsyncmethod/include)
1619
17if (USE_GLES)20if (USE_GLES)
18 compiz_plugin(opengl PLUGINDEPS composite CFLAGSADD "-DUSE_GLES -std=c++0x" LIBRARIES ${OPENGLES2_LIBRARIES} ${INTERNAL_LIBRARIES} dl INCDIRS ${OPENGLES2_INCLUDE_DIR})21 compiz_plugin(opengl PLUGINDEPS composite CFLAGSADD "-DUSE_GLES -std=c++0x" LIBRARIES ${OPENGLES2_LIBRARIES} ${INTERNAL_LIBRARIES} dl INCDIRS ${OPENGLES2_INCLUDE_DIR})
1922
=== modified file 'plugins/opengl/include/opengl/doublebuffer.h'
--- plugins/opengl/include/opengl/doublebuffer.h 2012-09-12 03:55:21 +0000
+++ plugins/opengl/include/opengl/doublebuffer.h 2012-09-22 03:12:18 +0000
@@ -2,6 +2,7 @@
2#define _COMPIZ_OPENGL_BUFFERBLIT_H2#define _COMPIZ_OPENGL_BUFFERBLIT_H
33
4#include <core/region.h>4#include <core/region.h>
5#include <vsyncmethod.h>
56
6namespace compiz7namespace compiz
7{8{
@@ -11,7 +12,7 @@
11class DoubleBuffer12class DoubleBuffer
12{13{
13 public:14 public:
14 DoubleBuffer ();15 DoubleBuffer (const std::list <VSyncMethod::Ptr> &vsyncMethods);
15 virtual ~DoubleBuffer ();16 virtual ~DoubleBuffer ();
1617
17 virtual void swap () const = 0;18 virtual void swap () const = 0;
@@ -31,9 +32,17 @@
3132
32 void set (Setting name, bool value);33 void set (Setting name, bool value);
33 void render (const CompRegion &region, bool fullscreen);34 void render (const CompRegion &region, bool fullscreen);
35 void vsync (BufferSwapType swapType);
36
37 bool hardwareVSyncFunctional ();
3438
35 protected:39 protected:
36 bool setting[_NSETTINGS];40 bool setting[_NSETTINGS];
41
42 private:
43 unsigned int unthrottledFrames;
44 std::list <VSyncMethod::Ptr> vsyncMethods;
45 VSyncMethod::Ptr lastSuccessfulVSyncMethod;
37};46};
3847
39}48}
4049
=== modified file 'plugins/opengl/src/doublebuffer/CMakeLists.txt'
--- plugins/opengl/src/doublebuffer/CMakeLists.txt 2012-07-05 08:17:49 +0000
+++ plugins/opengl/src/doublebuffer/CMakeLists.txt 2012-09-22 03:12:18 +0000
@@ -1,6 +1,7 @@
1INCLUDE_DIRECTORIES ( 1INCLUDE_DIRECTORIES (
2 ${compiz_SOURCE_DIR}/src/logmessage/include2 ${compiz_SOURCE_DIR}/src/logmessage/include
3 ${CMAKE_CURRENT_SOURCE_DIR}/../../include3 ${CMAKE_CURRENT_SOURCE_DIR}/../../include
4 ${CMAKE_CURRENT_SOURCE_DIR}/../../src
4 ${CMAKE_CURRENT_SOURCE_DIR}/src5 ${CMAKE_CURRENT_SOURCE_DIR}/src
5 6
6 ${Boost_INCLUDE_DIRS}7 ${Boost_INCLUDE_DIRS}
78
=== modified file 'plugins/opengl/src/doublebuffer/src/double-buffer.cpp'
--- plugins/opengl/src/doublebuffer/src/double-buffer.cpp 2012-09-12 03:55:21 +0000
+++ plugins/opengl/src/doublebuffer/src/double-buffer.cpp 2012-09-22 03:12:18 +0000
@@ -38,7 +38,9 @@
38namespace opengl38namespace opengl
39{39{
4040
41DoubleBuffer::DoubleBuffer ()41DoubleBuffer::DoubleBuffer (const std::list <VSyncMethod::Ptr> &vsyncMethods) :
42 unthrottledFrames (0),
43 vsyncMethods (vsyncMethods)
42{44{
43 setting[VSYNC] = true;45 setting[VSYNC] = true;
44 setting[HAVE_PERSISTENT_BACK_BUFFER] = false;46 setting[HAVE_PERSISTENT_BACK_BUFFER] = false;
@@ -61,23 +63,74 @@
61{63{
62 if (fullscreen)64 if (fullscreen)
63 {65 {
66 if (setting[VSYNC])
67 vsync (Flip);
68
64 swap ();69 swap ();
70
65 if (setting[NEED_PERSISTENT_BACK_BUFFER] &&71 if (setting[NEED_PERSISTENT_BACK_BUFFER] &&
66 !setting[HAVE_PERSISTENT_BACK_BUFFER])72 !setting[HAVE_PERSISTENT_BACK_BUFFER])
67 {73 {
68 copyFrontToBack ();74 copyFrontToBack ();
69 }75 }
70 }76 }
71 else if (blitAvailable ())77 else
72 blit (region);78 {
73 else if (fallbackBlitAvailable ())79 if (setting[VSYNC])
74 fallbackBlit (region);80 vsync (PartialCopy);
75 else81
76 {82 if (blitAvailable ())
77 // This will never happen unless you make a porting mistake...83 blit (region);
78 assert (false);84 else if (fallbackBlitAvailable ())
79 abort ();85 fallbackBlit (region);
80 }86 else
87 {
88 // This will never happen unless you make a porting mistake...
89 assert (false);
90 abort ();
91 }
92 }
93}
94
95void
96DoubleBuffer::vsync (BufferSwapType swapType)
97{
98 bool throttled = true;
99
100 for (std::list <VSyncMethod::Ptr>::iterator it = vsyncMethods.begin ();
101 it != vsyncMethods.end ();
102 ++it)
103 {
104 VSyncMethod::Ptr &method (*it);
105
106 /* Try and use this method, check if this method
107 * throttled us too */
108 if (method->enableForBufferSwapType (swapType, throttled))
109 {
110 if (lastSuccessfulVSyncMethod &&
111 lastSuccessfulVSyncMethod != method)
112 lastSuccessfulVSyncMethod->disable ();
113
114 lastSuccessfulVSyncMethod = method;
115 break;
116 }
117 else
118 {
119 throttled = false;
120 method->disable ();
121 }
122 }
123
124 if (!throttled)
125 unthrottledFrames++;
126 else
127 unthrottledFrames = 0;
128}
129
130bool
131DoubleBuffer::hardwareVSyncFunctional ()
132{
133 return unthrottledFrames < 5;
81}134}
82135
83} // namespace opengl136} // namespace opengl
84137
=== modified file 'plugins/opengl/src/doublebuffer/tests/test-opengl-double-buffer.cpp'
--- plugins/opengl/src/doublebuffer/tests/test-opengl-double-buffer.cpp 2012-09-12 10:45:58 +0000
+++ plugins/opengl/src/doublebuffer/tests/test-opengl-double-buffer.cpp 2012-09-22 03:12:18 +0000
@@ -2,17 +2,24 @@
2#include <gmock/gmock.h>2#include <gmock/gmock.h>
33
4#include <opengl/doublebuffer.h>4#include <opengl/doublebuffer.h>
5#include <vsyncmethod.h>
56
6using namespace compiz::opengl;7using namespace compiz::opengl;
7using testing::_;8using testing::_;
8using testing::StrictMock;9using testing::StrictMock;
9using testing::Return;10using testing::Return;
11using testing::SetArgReferee;
1012
11class MockDoubleBuffer :13class MockDoubleBuffer :
12 public DoubleBuffer14 public DoubleBuffer
13{15{
14 public:16 public:
1517
18 MockDoubleBuffer (const std::list <VSyncMethod::Ptr> &vsyncMethods) :
19 DoubleBuffer (vsyncMethods)
20 {
21 }
22
16 MOCK_CONST_METHOD0 (swap, void ());23 MOCK_CONST_METHOD0 (swap, void ());
17 MOCK_CONST_METHOD0 (blitAvailable, bool ());24 MOCK_CONST_METHOD0 (blitAvailable, bool ());
18 MOCK_CONST_METHOD1 (blit, void (const CompRegion &));25 MOCK_CONST_METHOD1 (blit, void (const CompRegion &));
@@ -21,13 +28,28 @@
21 MOCK_CONST_METHOD0 (copyFrontToBack, void ());28 MOCK_CONST_METHOD0 (copyFrontToBack, void ());
22};29};
2330
31class MockVSyncMethod :
32 public VSyncMethod
33{
34 public:
35
36 MOCK_METHOD2 (enableForBufferSwapType, bool (BufferSwapType, bool &));
37 MOCK_METHOD0 (disable, void ());
38};
39
24class DoubleBufferTest :40class DoubleBufferTest :
25 public ::testing::Test41 public ::testing::Test
26{42{
27 public:43 public:
2844
29 MockDoubleBuffer db;45 DoubleBufferTest () :
30 CompRegion blitRegion;46 db (vsyncMethods)
47 {
48 }
49
50 std::list <VSyncMethod::Ptr> vsyncMethods;
51 MockDoubleBuffer db;
52 CompRegion blitRegion;
3153
32};54};
3355
@@ -102,7 +124,8 @@
102124
103TEST_F(CompizOpenGLDoubleBufferDeathTest, TestNoPaintedFullscreenOrFBODoesNotBlitOrCopyIfNotSupportedAndDies)125TEST_F(CompizOpenGLDoubleBufferDeathTest, TestNoPaintedFullscreenOrFBODoesNotBlitOrCopyIfNotSupportedAndDies)
104{126{
105 StrictMock <MockDoubleBuffer> dbStrict;127 std::list <VSyncMethod::Ptr> vsyncMethods;
128 StrictMock <MockDoubleBuffer> dbStrict (vsyncMethods);
106129
107 ON_CALL (dbStrict, blitAvailable ()).WillByDefault (Return (false));130 ON_CALL (dbStrict, blitAvailable ()).WillByDefault (Return (false));
108 ON_CALL (dbStrict, fallbackBlitAvailable ()).WillByDefault (Return (false));131 ON_CALL (dbStrict, fallbackBlitAvailable ()).WillByDefault (Return (false));
@@ -115,7 +138,8 @@
115138
116TEST_F(DoubleBufferTest, TestSubBufferCopyIfNoFBOAndNoSubBufferBlit)139TEST_F(DoubleBufferTest, TestSubBufferCopyIfNoFBOAndNoSubBufferBlit)
117{140{
118 StrictMock <MockDoubleBuffer> dbStrict;141 std::list <VSyncMethod::Ptr> vsyncMethods;
142 StrictMock <MockDoubleBuffer> dbStrict (vsyncMethods);
119143
120 EXPECT_CALL (dbStrict, blitAvailable ()).WillOnce (Return (false));144 EXPECT_CALL (dbStrict, blitAvailable ()).WillOnce (Return (false));
121 EXPECT_CALL (dbStrict, fallbackBlitAvailable ()).WillOnce (Return (true));145 EXPECT_CALL (dbStrict, fallbackBlitAvailable ()).WillOnce (Return (true));
@@ -123,3 +147,141 @@
123147
124 dbStrict.render (blitRegion, false);148 dbStrict.render (blitRegion, false);
125}149}
150
151TEST (DoubleBufferVSyncTest, TestCallWorkingStrategy)
152{
153 boost::shared_ptr <MockVSyncMethod> mockVSyncMethod (new MockVSyncMethod ());
154 std::list <VSyncMethod::Ptr> vsyncMethods;
155
156 vsyncMethods.push_back (mockVSyncMethod);
157
158 MockDoubleBuffer doubleBuffer (vsyncMethods);
159
160 EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (Flip, _))
161 .WillOnce (Return (true));
162
163 doubleBuffer.vsync (Flip);
164}
165
166TEST (DoubleBufferVSyncTest, TestCallNextWorkingStrategy)
167{
168 boost::shared_ptr <MockVSyncMethod> mockVSyncMethod (new MockVSyncMethod ());
169 boost::shared_ptr <MockVSyncMethod> mockVSyncMethodSafer (new MockVSyncMethod ());
170 std::list <VSyncMethod::Ptr> vsyncMethods;
171
172 vsyncMethods.push_back (mockVSyncMethod);
173 vsyncMethods.push_back (mockVSyncMethodSafer);
174
175 MockDoubleBuffer doubleBuffer (vsyncMethods);
176
177 /* This one fails */
178 EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
179 .WillOnce (Return (false));
180 /* It needs to be deactivated */
181 EXPECT_CALL (*mockVSyncMethod, disable ());
182 /* Try the next one */
183 EXPECT_CALL (*mockVSyncMethodSafer, enableForBufferSwapType (PartialCopy, _))
184 .WillOnce (Return (true));
185
186 doubleBuffer.vsync (PartialCopy);
187}
188
189TEST (DoubleBufferVSyncTest, TestCallPrevCallNextPrevDeactivated)
190{
191 boost::shared_ptr <MockVSyncMethod> mockVSyncMethod (new MockVSyncMethod ());
192 boost::shared_ptr <MockVSyncMethod> mockVSyncMethodSafer (new MockVSyncMethod ());
193 std::list <VSyncMethod::Ptr> vsyncMethods;
194
195 vsyncMethods.push_back (mockVSyncMethod);
196 vsyncMethods.push_back (mockVSyncMethodSafer);
197
198 MockDoubleBuffer doubleBuffer (vsyncMethods);
199
200 /* This one fails */
201 EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
202 .WillOnce (Return (false));
203 /* It needs to be deactivated */
204 EXPECT_CALL (*mockVSyncMethod, disable ());
205 /* Try the next one */
206 EXPECT_CALL (*mockVSyncMethodSafer, enableForBufferSwapType (PartialCopy, _))
207 .WillOnce (Return (true));
208
209 doubleBuffer.vsync (PartialCopy);
210
211 /* Now the previous one works */
212 EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
213 .WillOnce (Return (true));
214 /* Previous one must be deactivated */
215 EXPECT_CALL (*mockVSyncMethodSafer, disable ());
216
217 doubleBuffer.vsync (PartialCopy);
218}
219
220TEST (DoubleBufferVSyncTest, TestReportNoHardwareVSyncIfMoreThan5UnthrottledFrames)
221{
222 boost::shared_ptr <MockVSyncMethod> mockVSyncMethod (new MockVSyncMethod ());
223 std::list <VSyncMethod::Ptr> vsyncMethods;
224
225 vsyncMethods.push_back (mockVSyncMethod);
226
227 /* Always succeed */
228 ON_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _)).WillByDefault (Return (true));
229
230 MockDoubleBuffer doubleBuffer (vsyncMethods);
231
232 /* This one succeeds but fails to throttle */
233 for (unsigned int i = 0; i < 5; ++i)
234 {
235 EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
236 .WillOnce (SetArgReferee <1> (false));
237
238 doubleBuffer.vsync (PartialCopy);
239 }
240
241 EXPECT_FALSE (doubleBuffer.hardwareVSyncFunctional ());
242}
243
244TEST (DoubleBufferVSyncTest, TestRestoreReportHardwareVSync)
245{
246 boost::shared_ptr <MockVSyncMethod> mockVSyncMethod (new MockVSyncMethod ());
247 std::list <VSyncMethod::Ptr> vsyncMethods;
248
249 vsyncMethods.push_back (mockVSyncMethod);
250
251 MockDoubleBuffer doubleBuffer (vsyncMethods);
252
253 /* Always succeed */
254 ON_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _)).WillByDefault (Return (true));
255
256 /* This one succeeds but fails to throttle */
257 for (unsigned int i = 0; i < 5; ++i)
258 {
259 EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
260 .WillOnce (SetArgReferee <1> (false));
261
262 EXPECT_TRUE (doubleBuffer.hardwareVSyncFunctional ());
263
264 doubleBuffer.vsync (PartialCopy);
265 }
266
267 EXPECT_FALSE (doubleBuffer.hardwareVSyncFunctional ());
268
269 /* It works again */
270 EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
271 .WillOnce (SetArgReferee <1> (true));
272
273 doubleBuffer.vsync (PartialCopy);
274
275 /* And should report to work for another 5 bad frames */
276 for (unsigned int i = 0; i < 5; ++i)
277 {
278 EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
279 .WillOnce (SetArgReferee <1> (false));
280
281 EXPECT_TRUE (doubleBuffer.hardwareVSyncFunctional ());
282
283 doubleBuffer.vsync (PartialCopy);
284 }
285
286 EXPECT_FALSE (doubleBuffer.hardwareVSyncFunctional ());
287}
126288
=== modified file 'plugins/opengl/src/privates.h'
--- plugins/opengl/src/privates.h 2012-09-20 09:35:40 +0000
+++ plugins/opengl/src/privates.h 2012-09-22 03:12:18 +0000
@@ -28,6 +28,8 @@
28#ifndef _OPENGL_PRIVATES_H28#ifndef _OPENGL_PRIVATES_H
29#define _OPENGL_PRIVATES_H29#define _OPENGL_PRIVATES_H
3030
31#include <memory>
32
31#include <composite/composite.h>33#include <composite/composite.h>
32#include <opengl/opengl.h>34#include <opengl/opengl.h>
33#include <core/atoms.h>35#include <core/atoms.h>
@@ -44,13 +46,23 @@
4446
45extern CompOutput *targetOutput;47extern CompOutput *targetOutput;
4648
49namespace compiz
50{
51 namespace opengl
52 {
53 class VSyncMethod;
54 typedef boost::shared_ptr <VSyncMethod> VSyncMethodPtr;
55 }
56}
57
47class GLDoubleBuffer :58class GLDoubleBuffer :
48 public compiz::opengl::DoubleBuffer59 public compiz::opengl::DoubleBuffer
49{60{
50 public:61 public:
5162
52 GLDoubleBuffer (Display *,63 GLDoubleBuffer (Display *,
53 const CompSize &);64 const CompSize &,
65 const std::list <compiz::opengl::VSyncMethodPtr> &vsyncMethods);
5466
55 protected:67 protected:
5668
@@ -65,9 +77,10 @@
65{77{
66 public:78 public:
6779
68 GLXDoubleBuffer (Display *,80 GLXDoubleBuffer (Display *,
69 const CompSize &,81 const CompSize &,
70 Window);82 Window ,
83 const std::list <compiz::opengl::VSyncMethodPtr> &vsyncMethods);
7184
72 void swap () const;85 void swap () const;
73 bool blitAvailable () const;86 bool blitAvailable () const;
@@ -88,9 +101,10 @@
88{101{
89 public:102 public:
90103
91 EGLDoubleBuffer (Display *,104 EGLDoubleBuffer (Display *,
92 const CompSize &,105 const CompSize &,
93 EGLSurface const &);106 EGLSurface const &,
107 const std::list <compiz::opengl::VSyncMethodPtr> &vsyncMethods);
94108
95 void swap () const;109 void swap () const;
96 bool blitAvailable () const;110 bool blitAvailable () const;
@@ -181,12 +195,12 @@
181 #ifdef USE_GLES195 #ifdef USE_GLES
182 EGLContext ctx;196 EGLContext ctx;
183 EGLSurface surface;197 EGLSurface surface;
184 EGLDoubleBuffer doubleBuffer;198 std::auto_ptr <EGLDoubleBuffer> doubleBuffer;
185 #else199 #else
186 GLXContext ctx;200 GLXContext ctx;
187201
188 GL::GLXGetProcAddressProc getProcAddress;202 GL::GLXGetProcAddressProc getProcAddress;
189 GLXDoubleBuffer doubleBuffer;203 std::auto_ptr <GLXDoubleBuffer> doubleBuffer;
190 #endif204 #endif
191205
192 GLFramebufferObject *scratchFbo;206 GLFramebufferObject *scratchFbo;
193207
=== modified file 'plugins/opengl/src/screen.cpp'
--- plugins/opengl/src/screen.cpp 2012-09-20 09:35:40 +0000
+++ plugins/opengl/src/screen.cpp 2012-09-22 03:12:18 +0000
@@ -32,7 +32,13 @@
32#endif32#endif
33#include <errno.h>33#include <errno.h>
3434
35#include <boost/bind.hpp>
36#include <boost/make_shared.hpp>
37
35#include "privates.h"38#include "privates.h"
39#include "vsyncmethod.h"
40#include "vsync-method-swap-interval.h"
41#include "vsync-method-wait-video-sync.h"
3642
37#include <dlfcn.h>43#include <dlfcn.h>
38#include <math.h>44#include <math.h>
@@ -162,7 +168,6 @@
162 bool canDoSlightlySaturated = false;168 bool canDoSlightlySaturated = false;
163169
164 unsigned int vsyncCount = 0;170 unsigned int vsyncCount = 0;
165 unsigned int unthrottledFrames = 0;
166171
167 bool stencilBuffer = false;172 bool stencilBuffer = false;
168#ifndef USE_GLES173#ifndef USE_GLES
@@ -271,9 +276,70 @@
271 GLScreen *gScreen;276 GLScreen *gScreen;
272};277};
273278
279#ifndef USE_GLES
280
281namespace compiz
282{
283 namespace opengl
284 {
285 void swapIntervalGLX (int interval)
286 {
287 // Docs: http://www.opengl.org/registry/specs/SGI/swap_control.txt
288 if (GL::swapInterval)
289 (*GL::swapInterval) (interval);
290 }
291
292 int waitVSyncGLX (int wait,
293 int remainder,
294 unsigned int *count)
295 {
296 /*
297 * While glXSwapBuffers/glXCopySubBufferMESA are meant to do a
298 * flush before they blit, it is best to not let that happen.
299 * Because that flush would occur after GL::waitVideoSync, causing
300 * a delay and the final blit to be slightly out of sync resulting
301 * in tearing. So we need to do a glFinish before we wait for
302 * vsync, to absolutely minimize tearing.
303 */
304 glFinish ();
305
306 // Docs: http://www.opengl.org/registry/specs/SGI/video_sync.txt
307 if (GL::waitVideoSync)
308 return (*GL::waitVideoSync) (wait, remainder, count);
309
310 return 0;
311 }
312 }
313}
314
315#else
316
317namespace compiz
318{
319 namespace opengl
320 {
321 void swapIntervalEGL (Display *display, int interval)
322 {
323 eglSwapInterval (eglGetDisplay (display), interval);
324 }
325
326 int waitVSyncEGL (int wait,
327 int remainder,
328 int *count)
329 {
330 /* not supported */
331 return 0;
332 }
333 }
334}
335
336#endif
337
274bool338bool
275GLScreen::glInitContext (XVisualInfo *visinfo)339GLScreen::glInitContext (XVisualInfo *visinfo)
276{340{
341 std::list <compiz::opengl::VSyncMethod::Ptr> availableVSyncMethods;
342
277 #ifdef USE_GLES343 #ifdef USE_GLES
278 Display *xdpy;344 Display *xdpy;
279 Window overlay;345 Window overlay;
@@ -497,6 +563,14 @@
497 priv->filter[SCREEN_TRANS_FILTER] = GLTexture::Good;563 priv->filter[SCREEN_TRANS_FILTER] = GLTexture::Good;
498 priv->filter[WINDOW_TRANS_FILTER] = GLTexture::Good;564 priv->filter[WINDOW_TRANS_FILTER] = GLTexture::Good;
499565
566 availableVSyncMethods.push_back (boost::make_shared <impl::SwapIntervalVSyncMethod> (
567 boost::bind (swapIntervalEGL, screen->dpy (), _1)));
568
569 priv->doubleBuffer.reset (new EGLDoubleBuffer (screen->dpy (),
570 *screen,
571 priv->surface,
572 availableVSyncMethods));
573
500 if (GL::textureFromPixmap)574 if (GL::textureFromPixmap)
501 registerBindPixmap (EglTexture::bindPixmapToTexture);575 registerBindPixmap (EglTexture::bindPixmapToTexture);
502576
@@ -794,6 +868,16 @@
794 priv->filter[SCREEN_TRANS_FILTER] = GLTexture::Good;868 priv->filter[SCREEN_TRANS_FILTER] = GLTexture::Good;
795 priv->filter[WINDOW_TRANS_FILTER] = GLTexture::Good;869 priv->filter[WINDOW_TRANS_FILTER] = GLTexture::Good;
796870
871 availableVSyncMethods.push_back (boost::make_shared <impl::SwapIntervalVSyncMethod> (
872 boost::bind (swapIntervalGLX, _1)));
873 availableVSyncMethods.push_back (boost::make_shared <impl::WaitVSyncMethod> (
874 boost::bind (waitVSyncGLX, _1, _2, _3)));
875
876 priv->doubleBuffer.reset (new GLXDoubleBuffer (screen->dpy (),
877 *screen,
878 priv->cScreen->output (),
879 availableVSyncMethods));
880
797 if (GL::textureFromPixmap)881 if (GL::textureFromPixmap)
798 registerBindPixmap (TfpTexture::bindPixmapToTexture);882 registerBindPixmap (TfpTexture::bindPixmapToTexture);
799#endif883#endif
@@ -1120,9 +1204,6 @@
1120 lighting (false),1204 lighting (false),
1121 #ifndef USE_GLES1205 #ifndef USE_GLES
1122 getProcAddress (0),1206 getProcAddress (0),
1123 doubleBuffer (screen->dpy (), *screen, cScreen->output ()),
1124 #else
1125 doubleBuffer (screen->dpy (), *screen, surface),
1126 #endif1207 #endif
1127 scratchFbo (NULL),1208 scratchFbo (NULL),
1128 outputRegion (),1209 outputRegion (),
@@ -1670,61 +1751,17 @@
1670 return &priv->shaderCache.getShaderData(params);1751 return &priv->shaderCache.getShaderData(params);
1671}1752}
16721753
1754
1755
1673namespace GL1756namespace GL
1674{1757{
16751758
1676void
1677waitForVideoSync ()
1678{
1679#ifndef USE_GLES
1680 GL::unthrottledFrames++;
1681 if (GL::waitVideoSync)
1682 {
1683 // Don't wait twice. Just in case.
1684 if (GL::swapInterval)
1685 (*GL::swapInterval) (0);
1686
1687 /*
1688 * While glXSwapBuffers/glXCopySubBufferMESA are meant to do a
1689 * flush before they blit, it is best to not let that happen.
1690 * Because that flush would occur after GL::waitVideoSync, causing
1691 * a delay and the final blit to be slightly out of sync resulting
1692 * in tearing. So we need to do a glFinish before we wait for
1693 * vsync, to absolutely minimize tearing.
1694 */
1695 glFinish ();
1696
1697 // Docs: http://www.opengl.org/registry/specs/SGI/video_sync.txt
1698 unsigned int oldCount = GL::vsyncCount;
1699 (*GL::waitVideoSync) (1, 0, &GL::vsyncCount);
1700
1701 if (GL::vsyncCount != oldCount)
1702 GL::unthrottledFrames = 0;
1703 }
1704#endif
1705}
1706
1707void
1708controlSwapVideoSync (bool sync)
1709{
1710#ifndef USE_GLES
1711 // Docs: http://www.opengl.org/registry/specs/SGI/swap_control.txt
1712 if (GL::swapInterval)
1713 {
1714 (*GL::swapInterval) (sync ? 1 : 0);
1715 GL::unthrottledFrames++;
1716 }
1717 else if (sync)
1718 waitForVideoSync ();
1719#else
1720 eglSwapInterval (eglGetDisplay (screen->dpy ()), sync ? 1 : 0);
1721 GL::unthrottledFrames++;
1722#endif
1723}
1724
1725} // namespace GL1759} // namespace GL
17261760
1727GLDoubleBuffer::GLDoubleBuffer (Display *d, const CompSize &s) :1761GLDoubleBuffer::GLDoubleBuffer (Display *d,
1762 const CompSize &s,
1763 const std::list <VSyncMethod::Ptr> &vsyncMethods) :
1764 compiz::opengl::DoubleBuffer (vsyncMethods),
1728 mDpy (d),1765 mDpy (d),
1729 mSize (s)1766 mSize (s)
1730{1767{
@@ -1757,10 +1794,11 @@
1757 glMatrixMode (GL_MODELVIEW);1794 glMatrixMode (GL_MODELVIEW);
1758}1795}
17591796
1760GLXDoubleBuffer::GLXDoubleBuffer (Display *d,1797GLXDoubleBuffer::GLXDoubleBuffer (Display *d,
1761 const CompSize &s,1798 const CompSize &s,
1762 Window output) :1799 Window output,
1763 GLDoubleBuffer (d, s),1800 const std::list <VSyncMethodPtr> &vsyncMethods) :
1801 GLDoubleBuffer (d, s, vsyncMethods),
1764 mOutput (output)1802 mOutput (output)
1765{1803{
1766}1804}
@@ -1768,8 +1806,6 @@
1768void1806void
1769GLXDoubleBuffer::swap () const1807GLXDoubleBuffer::swap () const
1770{1808{
1771 GL::controlSwapVideoSync (setting[VSYNC]);
1772
1773 glXSwapBuffers (mDpy, mOutput);1809 glXSwapBuffers (mDpy, mOutput);
1774}1810}
17751811
@@ -1784,9 +1820,6 @@
1784{1820{
1785 const CompRect::vector &blitRects (region.rects ());1821 const CompRect::vector &blitRects (region.rects ());
17861822
1787 if (setting[VSYNC])
1788 GL::waitForVideoSync ();
1789
1790 foreach (const CompRect &r, blitRects)1823 foreach (const CompRect &r, blitRects)
1791 {1824 {
1792 int y = mSize.height () - r.y2 ();1825 int y = mSize.height () - r.y2 ();
@@ -1808,9 +1841,6 @@
1808 int w = screen->width ();1841 int w = screen->width ();
1809 int h = screen->height ();1842 int h = screen->height ();
18101843
1811 if (setting[VSYNC])
1812 GL::waitForVideoSync ();
1813
1814 glMatrixMode (GL_PROJECTION);1844 glMatrixMode (GL_PROJECTION);
1815 glPushMatrix ();1845 glPushMatrix ();
1816 glLoadIdentity ();1846 glLoadIdentity ();
@@ -1840,10 +1870,11 @@
18401870
1841#else1871#else
18421872
1843EGLDoubleBuffer::EGLDoubleBuffer (Display *d,1873EGLDoubleBuffer::EGLDoubleBuffer (Display *d,
1844 const CompSize &s,1874 const CompSize &s,
1845 EGLSurface const & surface) :1875 EGLSurface const &surface,
1846 GLDoubleBuffer (d, s),1876 const std::list <VSyncMethodPtr> &vsyncMethods) :
1877 GLDoubleBuffer (d, s, vsyncMethods),
1847 mSurface (surface)1878 mSurface (surface)
1848{1879{
1849}1880}
@@ -1851,8 +1882,6 @@
1851void1882void
1852EGLDoubleBuffer::swap () const1883EGLDoubleBuffer::swap () const
1853{1884{
1854 GL::controlSwapVideoSync (setting[VSYNC]);
1855
1856 eglSwapBuffers (eglGetDisplay (mDpy), mSurface);1885 eglSwapBuffers (eglGetDisplay (mDpy), mSurface);
1857 eglWaitGL ();1886 eglWaitGL ();
1858 XFlush (mDpy);1887 XFlush (mDpy);
@@ -1870,8 +1899,6 @@
1870 CompRect::vector blitRects (region.rects ());1899 CompRect::vector blitRects (region.rects ());
1871 int y = 0;1900 int y = 0;
18721901
1873 GL::controlSwapVideoSync (setting[VSYNC]);
1874
1875 foreach (const CompRect &r, blitRects)1902 foreach (const CompRect &r, blitRects)
1876 {1903 {
1877 y = mSize.height () - r.y2 ();1904 y = mSize.height () - r.y2 ();
@@ -2052,10 +2079,10 @@
2052 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&2079 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
2053 commonFrontbuffer);2080 commonFrontbuffer);
20542081
2055 doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());2082 doubleBuffer->set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());
2056 doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);2083 doubleBuffer->set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);
2057 doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);2084 doubleBuffer->set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);
2058 doubleBuffer.render (tmpRegion, fullscreen);2085 doubleBuffer->render (tmpRegion, fullscreen);
20592086
2060 lastMask = mask;2087 lastMask = mask;
2061}2088}
@@ -2066,8 +2093,8 @@
2066 #ifdef USE_GLES2093 #ifdef USE_GLES
2067 return false;2094 return false;
2068 #else2095 #else
2069 return GL::waitVideoSync && optionGetSyncToVblank () && 2096 return GL::waitVideoSync && optionGetSyncToVblank () &&
2070 GL::unthrottledFrames < 5;2097 doubleBuffer->hardwareVSyncFunctional ();
2071 #endif2098 #endif
2072}2099}
20732100
20742101
=== added directory 'plugins/opengl/src/vsyncmethod'
=== added file 'plugins/opengl/src/vsyncmethod.h'
--- plugins/opengl/src/vsyncmethod.h 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/vsyncmethod.h 2012-09-22 03:12:18 +0000
@@ -0,0 +1,61 @@
1/*
2 * Compiz, opengl plugin, vsync methods
3 *
4 * Copyright © 2012 Canonical Ltd.
5 * Copyright © 2008 Dennis Kasprzyk
6 * Copyright © 2007 Novell, Inc.
7 *
8 * Permission to use, copy, modify, distribute, and sell this software
9 * and its documentation for any purpose is hereby granted without
10 * fee, provided that the above copyright notice appear in all copies
11 * and that both that copyright notice and this permission notice
12 * appear in supporting documentation, and that the name of
13 * Dennis Kasprzyk not be used in advertising or publicity pertaining to
14 * distribution of the software without specific, written prior permission.
15 * Dennis Kasprzyk makes no representations about the suitability of this
16 * software for any purpose. It is provided "as is" without express or
17 * implied warranty.
18 *
19 * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
21 * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
23 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
24 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 *
27 * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
28 * David Reveman <davidr@novell.com>
29 * Daniel van Vugt <daniel.van.vugt@canonical.com>
30 * Sam Spilsbury <sam.spilsbury@canonical.com>
31 */
32#ifndef _COMPIZ_OPENGL_VSYNC_METHOD_H
33#define _COMPIZ_OPENGL_VSYNC_METHOD_H
34
35#include <boost/shared_ptr.hpp>
36
37namespace compiz
38{
39 namespace opengl
40 {
41 typedef enum _BufferSwapType
42 {
43 Flip,
44 PartialCopy
45 } BufferSwapType;
46
47 class VSyncMethod
48 {
49 public:
50
51 typedef boost::shared_ptr <VSyncMethod> Ptr;
52
53 virtual bool enableForBufferSwapType (BufferSwapType type,
54 bool &throttledFrame) = 0;
55 virtual void disable () = 0;
56 };
57 }
58}
59
60#endif
61
062
=== added file 'plugins/opengl/src/vsyncmethod/CMakeLists.txt'
--- plugins/opengl/src/vsyncmethod/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/vsyncmethod/CMakeLists.txt 2012-09-22 03:12:18 +0000
@@ -0,0 +1,25 @@
1INCLUDE_DIRECTORIES (
2 ${CMAKE_CURRENT_SOURCE_DIR}/../../src
3 ${CMAKE_CURRENT_SOURCE_DIR}/include
4 ${CMAKE_CURRENT_SOURCE_DIR}/src
5
6 ${Boost_INCLUDE_DIRS}
7)
8
9LINK_DIRECTORIES (${COMPIZ_LIBRARY_DIRS})
10
11SET(
12 SRCS
13 ${CMAKE_CURRENT_SOURCE_DIR}/src/vsync-method-swap-interval.cpp
14 ${CMAKE_CURRENT_SOURCE_DIR}/src/vsync-method-wait-video-sync.cpp
15)
16
17ADD_LIBRARY(
18 compiz_opengl_vsync_methods STATIC
19
20 ${SRCS}
21)
22
23if (COMPIZ_BUILD_TESTING)
24ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
25endif (COMPIZ_BUILD_TESTING)
026
=== added directory 'plugins/opengl/src/vsyncmethod/include'
=== added file 'plugins/opengl/src/vsyncmethod/include/vsync-method-swap-interval.h'
--- plugins/opengl/src/vsyncmethod/include/vsync-method-swap-interval.h 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/vsyncmethod/include/vsync-method-swap-interval.h 2012-09-22 03:12:18 +0000
@@ -0,0 +1,67 @@
1/*
2 * Compiz, opengl plugin, vsync methods
3 *
4 * Copyright © 2012 Canonical Ltd.
5 * Copyright © 2008 Dennis Kasprzyk
6 * Copyright © 2007 Novell, Inc.
7 *
8 * Permission to use, copy, modify, distribute, and sell this software
9 * and its documentation for any purpose is hereby granted without
10 * fee, provided that the above copyright notice appear in all copies
11 * and that both that copyright notice and this permission notice
12 * appear in supporting documentation, and that the name of
13 * Dennis Kasprzyk not be used in advertising or publicity pertaining to
14 * distribution of the software without specific, written prior permission.
15 * Dennis Kasprzyk makes no representations about the suitability of this
16 * software for any purpose. It is provided "as is" without express or
17 * implied warranty.
18 *
19 * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
21 * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
23 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
24 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 *
27 * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
28 * David Reveman <davidr@novell.com>
29 * Daniel van Vugt <daniel.van.vugt@canonical.com>
30 * Sam Spilsbury <sam.spilsbury@canonical.com>
31 */
32#ifndef _COMPIZ_OPENGL_VSYNC_METHOD_SWAP_INTERVAL_H
33#define _COMPIZ_OPENGL_VSYNC_METHOD_SWAP_INTERVAL_H
34
35#include <memory>
36#include <boost/function.hpp>
37#include <vsyncmethod.h>
38
39namespace compiz
40{
41 namespace opengl
42 {
43 namespace impl
44 {
45 namespace cgl = compiz::opengl;
46 typedef boost::function <void (int)> GLXSwapIntervalEXTFunc;
47
48 class PrivateSwapIntervalVSyncMethod;
49 class SwapIntervalVSyncMethod :
50 public cgl::VSyncMethod
51 {
52 public:
53
54 SwapIntervalVSyncMethod (const GLXSwapIntervalEXTFunc &swapIntervalEXT);
55
56 bool enableForBufferSwapType (cgl::BufferSwapType type,
57 bool &throttledFrame);
58 void disable ();
59
60 private:
61
62 std::auto_ptr <PrivateSwapIntervalVSyncMethod> priv;
63 };
64 }
65 } // namespace opengl
66} // namespace compiz
67#endif
068
=== added file 'plugins/opengl/src/vsyncmethod/include/vsync-method-wait-video-sync.h'
--- plugins/opengl/src/vsyncmethod/include/vsync-method-wait-video-sync.h 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/vsyncmethod/include/vsync-method-wait-video-sync.h 2012-09-22 03:12:18 +0000
@@ -0,0 +1,67 @@
1/*
2 * Compiz, opengl plugin, vsync methods
3 *
4 * Copyright © 2012 Canonical Ltd.
5 * Copyright © 2008 Dennis Kasprzyk
6 * Copyright © 2007 Novell, Inc.
7 *
8 * Permission to use, copy, modify, distribute, and sell this software
9 * and its documentation for any purpose is hereby granted without
10 * fee, provided that the above copyright notice appear in all copies
11 * and that both that copyright notice and this permission notice
12 * appear in supporting documentation, and that the name of
13 * Dennis Kasprzyk not be used in advertising or publicity pertaining to
14 * distribution of the software without specific, written prior permission.
15 * Dennis Kasprzyk makes no representations about the suitability of this
16 * software for any purpose. It is provided "as is" without express or
17 * implied warranty.
18 *
19 * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
21 * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
23 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
24 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 *
27 * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
28 * David Reveman <davidr@novell.com>
29 * Daniel van Vugt <daniel.van.vugt@canonical.com>
30 * Sam Spilsbury <sam.spilsbury@canonical.com>
31 */
32#ifndef _COMPIZ_OPENGL_VSYNC_METHOD_WAIT_VIDEO_SYNC_H
33#define _COMPIZ_OPENGL_VSYNC_METHOD_WAIT_VIDEO_SYNC_H
34
35#include <memory>
36#include <boost/function.hpp>
37#include <vsyncmethod.h>
38
39namespace compiz
40{
41 namespace opengl
42 {
43 namespace impl
44 {
45 namespace cgl = compiz::opengl;
46 typedef boost::function <int (int, int, unsigned int *)> GLXWaitVideoSyncSGIFunc;
47
48 class PrivateWaitVSyncMethod;
49 class WaitVSyncMethod :
50 public cgl::VSyncMethod
51 {
52 public:
53
54 WaitVSyncMethod (const GLXWaitVideoSyncSGIFunc &);
55
56 bool enableForBufferSwapType (cgl::BufferSwapType type,
57 bool &throttledFrame);
58 void disable ();
59
60 private:
61
62 std::auto_ptr <PrivateWaitVSyncMethod> priv;
63 };
64 }
65 } // namespace opengl
66} // namespace compiz
67#endif
068
=== added directory 'plugins/opengl/src/vsyncmethod/src'
=== added file 'plugins/opengl/src/vsyncmethod/src/vsync-method-swap-interval.cpp'
--- plugins/opengl/src/vsyncmethod/src/vsync-method-swap-interval.cpp 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/vsyncmethod/src/vsync-method-swap-interval.cpp 2012-09-22 03:12:18 +0000
@@ -0,0 +1,100 @@
1/*
2 * Compiz, opengl plugin, vsync methods
3 *
4 * Copyright © 2012 Canonical Ltd.
5 * Copyright © 2008 Dennis Kasprzyk
6 * Copyright © 2007 Novell, Inc.
7 *
8 * Permission to use, copy, modify, distribute, and sell this software
9 * and its documentation for any purpose is hereby granted without
10 * fee, provided that the above copyright notice appear in all copies
11 * and that both that copyright notice and this permission notice
12 * appear in supporting documentation, and that the name of
13 * Dennis Kasprzyk not be used in advertising or publicity pertaining to
14 * distribution of the software without specific, written prior permission.
15 * Dennis Kasprzyk makes no representations about the suitability of this
16 * software for any purpose. It is provided "as is" without express or
17 * implied warranty.
18 *
19 * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
21 * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
23 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
24 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 *
27 * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
28 * David Reveman <davidr@novell.com>
29 * Daniel van Vugt <daniel.van.vugt@canonical.com>
30 * Sam Spilsbury <sam.spilsbury@canonical.com>
31 */
32#include <vsyncmethod.h>
33#include <vsync-method-swap-interval.h>
34
35namespace compiz
36{
37 namespace opengl
38 {
39 namespace impl
40 {
41 class PrivateSwapIntervalVSyncMethod
42 {
43 public:
44
45 PrivateSwapIntervalVSyncMethod (const GLXSwapIntervalEXTFunc &);
46
47 GLXSwapIntervalEXTFunc swapInterval;
48 bool enabled;
49 };
50 }
51 }
52}
53
54namespace cgl = compiz::opengl;
55namespace cgli = compiz::opengl::impl;
56
57cgli::PrivateSwapIntervalVSyncMethod::PrivateSwapIntervalVSyncMethod (const GLXSwapIntervalEXTFunc &swapInterval) :
58 swapInterval (swapInterval),
59 enabled (false)
60{
61}
62
63cgli::SwapIntervalVSyncMethod::SwapIntervalVSyncMethod (const GLXSwapIntervalEXTFunc &swapInterval) :
64 priv (new cgli::PrivateSwapIntervalVSyncMethod (swapInterval))
65{
66
67}
68
69bool
70cgli::SwapIntervalVSyncMethod::enableForBufferSwapType (cgl::BufferSwapType swapType,
71 bool &throttledFrame)
72{
73 /* Always consider these frames as un-throttled as the buffer
74 * swaps are done asynchronously */
75 throttledFrame = false;
76
77 /* Can't use swapInterval unless using SwapBuffers */
78 if (swapType != cgl::Flip)
79 return false;
80
81 /* Enable if not enabled */
82 if (!priv->enabled)
83 {
84 priv->swapInterval (1);
85 priv->enabled = true;
86 }
87
88 return true;
89}
90
91void
92cgli::SwapIntervalVSyncMethod::disable ()
93{
94 /* Disable if enabled */
95 if (priv->enabled)
96 {
97 priv->swapInterval (0);
98 priv->enabled = false;
99 }
100}
0101
=== added file 'plugins/opengl/src/vsyncmethod/src/vsync-method-wait-video-sync.cpp'
--- plugins/opengl/src/vsyncmethod/src/vsync-method-wait-video-sync.cpp 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/vsyncmethod/src/vsync-method-wait-video-sync.cpp 2012-09-22 03:12:18 +0000
@@ -0,0 +1,87 @@
1/*
2 * Compiz, opengl plugin, vsync methods
3 *
4 * Copyright © 2012 Canonical Ltd.
5 * Copyright © 2008 Dennis Kasprzyk
6 * Copyright © 2007 Novell, Inc.
7 *
8 * Permission to use, copy, modify, distribute, and sell this software
9 * and its documentation for any purpose is hereby granted without
10 * fee, provided that the above copyright notice appear in all copies
11 * and that both that copyright notice and this permission notice
12 * appear in supporting documentation, and that the name of
13 * Dennis Kasprzyk not be used in advertising or publicity pertaining to
14 * distribution of the software without specific, written prior permission.
15 * Dennis Kasprzyk makes no representations about the suitability of this
16 * software for any purpose. It is provided "as is" without express or
17 * implied warranty.
18 *
19 * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
21 * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
23 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
24 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 *
27 * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
28 * David Reveman <davidr@novell.com>
29 * Daniel van Vugt <daniel.van.vugt@canonical.com>
30 * Sam Spilsbury <sam.spilsbury@canonical.com>
31 */
32#include <vsyncmethod.h>
33#include <vsync-method-wait-video-sync.h>
34
35namespace compiz
36{
37 namespace opengl
38 {
39 namespace impl
40 {
41 class PrivateWaitVSyncMethod
42 {
43 public:
44
45 PrivateWaitVSyncMethod (const GLXWaitVideoSyncSGIFunc &);
46
47 GLXWaitVideoSyncSGIFunc waitVideoSync;
48 unsigned int lastVSyncCounter;
49 };
50 }
51 }
52}
53
54namespace cgl = compiz::opengl;
55namespace cgli = compiz::opengl::impl;
56
57cgli::PrivateWaitVSyncMethod::PrivateWaitVSyncMethod (const cgli::GLXWaitVideoSyncSGIFunc &waitVideoSync) :
58 waitVideoSync (waitVideoSync),
59 lastVSyncCounter (0)
60{
61}
62
63cgli::WaitVSyncMethod::WaitVSyncMethod (const cgli::GLXWaitVideoSyncSGIFunc &waitVideoSync) :
64 priv (new cgli::PrivateWaitVSyncMethod (waitVideoSync))
65{
66}
67
68bool
69cgli::WaitVSyncMethod::enableForBufferSwapType (cgl::BufferSwapType swapType,
70 bool &throttledFrame)
71{
72 unsigned int oldVideoSyncCounter = priv->lastVSyncCounter;
73 priv->waitVideoSync (1, 0, &priv->lastVSyncCounter);
74
75 /* Check if this frame was actually throttled */
76 if (priv->lastVSyncCounter == oldVideoSyncCounter)
77 throttledFrame = false;
78 else
79 throttledFrame = true;
80
81 return true;
82}
83
84void
85cgli::WaitVSyncMethod::disable ()
86{
87}
088
=== added directory 'plugins/opengl/src/vsyncmethod/tests'
=== added file 'plugins/opengl/src/vsyncmethod/tests/CMakeLists.txt'
--- plugins/opengl/src/vsyncmethod/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/vsyncmethod/tests/CMakeLists.txt 2012-09-22 03:12:18 +0000
@@ -0,0 +1,24 @@
1find_library (GMOCK_LIBRARY gmock)
2find_library (GMOCK_MAIN_LIBRARY gmock_main)
3
4if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
5 message ("Google Mock and Google Test not found - cannot build tests!")
6 set (COMPIZ_BUILD_TESTING OFF)
7endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
8
9include_directories (${GTEST_INCLUDE_DIRS})
10
11link_directories (${COMPIZ_LIBRARY_DIRS})
12
13add_executable (compiz_test_opengl_vsync_methods
14 ${CMAKE_CURRENT_SOURCE_DIR}/test-opengl-vsync-methods.cpp)
15
16target_link_libraries (compiz_test_opengl_vsync_methods
17 compiz_opengl_vsync_methods
18 ${GTEST_BOTH_LIBRARIES}
19 ${GMOCK_LIBRARY}
20 ${GMOCK_MAIN_LIBRARY}
21 ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
22 )
23
24compiz_discover_tests (compiz_test_opengl_vsync_methods COVERAGE compiz_opengl_vsync_methods)
025
=== added file 'plugins/opengl/src/vsyncmethod/tests/test-opengl-vsync-methods.cpp'
--- plugins/opengl/src/vsyncmethod/tests/test-opengl-vsync-methods.cpp 1970-01-01 00:00:00 +0000
+++ plugins/opengl/src/vsyncmethod/tests/test-opengl-vsync-methods.cpp 2012-09-22 03:12:18 +0000
@@ -0,0 +1,215 @@
1/*
2 * Compiz, opengl plugin, vsync methods
3 *
4 * Copyright © 2012 Canonical Ltd.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software
7 * and its documentation for any purpose is hereby granted without
8 * fee, provided that the above copyright notice appear in all copies
9 * and that both that copyright notice and this permission notice
10 * appear in supporting documentation, and that the name of
11 * Dennis Kasprzyk not be used in advertising or publicity pertaining to
12 * distribution of the software without specific, written prior permission.
13 * Dennis Kasprzyk makes no representations about the suitability of this
14 * software for any purpose. It is provided "as is" without express or
15 * implied warranty.
16 *
17 * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
19 * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
21 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
22 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
23 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 *
25 * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
26 */
27#include <boost/bind.hpp>
28
29#include <gtest/gtest.h>
30#include <gmock/gmock.h>
31
32#include <vsync-method-wait-video-sync.h>
33#include <vsync-method-swap-interval.h>
34
35namespace cgl = compiz::opengl;
36namespace cgli = compiz::opengl::impl;
37
38using ::testing::Return;
39using ::testing::DoAll;
40using ::testing::SetArgPointee;
41using ::testing::_;
42
43namespace
44{
45 class MockOpenGLFunctionsTable
46 {
47 public:
48
49 MOCK_METHOD3 (waitVideoSyncSGI, int (int, int, unsigned int *));
50 MOCK_METHOD1 (swapIntervalEXT, void (int));
51 };
52
53 cgli::GLXWaitVideoSyncSGIFunc
54 GetWaitVideoSyncFuncFromMock (MockOpenGLFunctionsTable &mock)
55 {
56 return boost::bind (&MockOpenGLFunctionsTable::waitVideoSyncSGI, &mock, _1, _2, _3);
57 }
58
59 cgli::GLXSwapIntervalEXTFunc
60 GetSwapIntervalFuncFromMock (MockOpenGLFunctionsTable &mock)
61 {
62 return boost::bind (&MockOpenGLFunctionsTable::swapIntervalEXT, &mock, _1);
63 }
64}
65
66class OpenGLSwapIntervalTest :
67 public ::testing::Test
68{
69 public:
70
71 OpenGLSwapIntervalTest () :
72 swapIntervalMethod (GetSwapIntervalFuncFromMock (functions))
73 {
74 }
75
76 MockOpenGLFunctionsTable functions;
77 cgli::SwapIntervalVSyncMethod swapIntervalMethod;
78};
79
80class OpenGLWaitVideoSyncTest :
81 public ::testing::Test
82{
83 public:
84
85 OpenGLWaitVideoSyncTest () :
86 waitVideoSyncMethod (GetWaitVideoSyncFuncFromMock (functions))
87 {
88 }
89
90 MockOpenGLFunctionsTable functions;
91 cgli::WaitVSyncMethod waitVideoSyncMethod;
92};
93
94TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalOnEnableForFlip)
95{
96 bool throttled;
97 EXPECT_CALL (functions, swapIntervalEXT (1));
98 EXPECT_TRUE (swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled));
99}
100
101TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalOnEnableForFlipOnlyOnce)
102{
103 bool throttled;
104 EXPECT_CALL (functions, swapIntervalEXT (1)).Times (1);
105 EXPECT_TRUE (swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled));
106 /* This is still meant to return true even though it does
107 * nothing it just means the operation succeeded */
108 EXPECT_TRUE (swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled));
109}
110
111TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalOnEnableForFlipAndZeroForDisable)
112{
113 bool throttled;
114 EXPECT_CALL (functions, swapIntervalEXT (1));
115 EXPECT_TRUE (swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled));
116 EXPECT_CALL (functions, swapIntervalEXT (0));
117 swapIntervalMethod.disable ();
118}
119
120TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalZeroForDisableOnce)
121{
122 bool throttled;
123 /* Enable it */
124 EXPECT_CALL (functions, swapIntervalEXT (1)).Times (1);
125 swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled);
126
127 /* Disable it twice */
128 EXPECT_CALL (functions, swapIntervalEXT (0)).Times (1);
129 swapIntervalMethod.disable ();
130 swapIntervalMethod.disable ();
131}
132
133TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalFailsToEnableForCopy)
134{
135 bool throttled;
136 EXPECT_FALSE (swapIntervalMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
137}
138
139TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalUnthrottledWhereFailure)
140{
141 bool throttled;
142 EXPECT_FALSE (swapIntervalMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
143 EXPECT_FALSE (throttled);
144}
145
146TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalUnthrottledWhereSuccess)
147{
148 bool throttled;
149 EXPECT_TRUE (swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled));
150 EXPECT_FALSE (throttled);
151}
152
153TEST_F (OpenGLWaitVideoSyncTest, TestCallsGetVideoSyncAndWaitVideoSyncForCopy)
154{
155 bool throttled;
156 EXPECT_CALL (functions, waitVideoSyncSGI (_, _, _));
157 EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
158}
159
160TEST_F (OpenGLWaitVideoSyncTest, TestCallsGetVideoSyncAndWaitVideoSyncForFlip)
161{
162 bool throttled;
163 EXPECT_CALL (functions, waitVideoSyncSGI (_, _, _));
164 EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::Flip, throttled));
165}
166
167TEST_F (OpenGLWaitVideoSyncTest, TestCallsWaitVideoSyncAndThrottled)
168{
169 bool throttled = false;
170
171 /* Frame 0 to frame 1 */
172 EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (1),
173 Return (0)));
174 /* Returned next frame, this frame was throttled */
175 EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
176 EXPECT_TRUE (throttled);
177}
178
179TEST_F (OpenGLWaitVideoSyncTest, TestCallsWaitVideoSyncAndThrottledEveryFrame)
180{
181 bool throttled = false;
182
183 /* Frame 0 to frame 1 */
184 EXPECT_CALL (functions, waitVideoSyncSGI (1, 0, _)).WillOnce (DoAll (SetArgPointee<2> (1),
185 Return (0)));
186 /* Returned next frame, this frame was throttled */
187 EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
188 EXPECT_TRUE (throttled);
189
190 /* Frame 1 to frame 2 */
191 EXPECT_CALL (functions, waitVideoSyncSGI (1, 0, _)).WillOnce (DoAll (SetArgPointee<2> (2),
192 Return (0)));
193 /* Returned next frame, this frame was throttled */
194 EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
195 EXPECT_TRUE (throttled);
196}
197
198TEST_F (OpenGLWaitVideoSyncTest, TestCallsWaitVideoSyncAndUnthrottledDueToBrokenWaitVSync)
199{
200 bool throttled = false;
201
202 /* Frame 0 to frame 1 */
203 EXPECT_CALL (functions, waitVideoSyncSGI (1, 0, _)).WillOnce (DoAll (SetArgPointee<2> (1),
204 Return (0)));
205 /* Returned next frame, this frame was throttled */
206 EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
207 EXPECT_TRUE (throttled);
208
209 /* Frame 1 to frame 1 (eg, broken waitVideoSyncSGI */
210 EXPECT_CALL (functions, waitVideoSyncSGI (1, 0, _)).WillOnce (DoAll (SetArgPointee<2> (1),
211 Return (0)));
212 /* Returned next frame, this frame was throttled */
213 EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
214 EXPECT_FALSE (throttled);
215}

Subscribers

People subscribed via source and target branches