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
1=== modified file 'plugins/opengl/CMakeLists.txt'
2--- plugins/opengl/CMakeLists.txt 2012-09-17 13:48:33 +0000
3+++ plugins/opengl/CMakeLists.txt 2012-09-22 03:12:18 +0000
4@@ -6,13 +6,16 @@
5 compiz_opengl_double_buffer
6 compiz_opengl_fsregion
7 compiz_opengl_glx_tfp_bind
8+ compiz_opengl_vsync_methods
9 )
10
11 add_subdirectory (src/doublebuffer)
12 add_subdirectory (src/fsregion)
13 add_subdirectory (src/glxtfpbind)
14+add_subdirectory (src/vsyncmethod)
15
16 include_directories (src/glxtfpbind/include)
17+include_directories (src/vsyncmethod/include)
18
19 if (USE_GLES)
20 compiz_plugin(opengl PLUGINDEPS composite CFLAGSADD "-DUSE_GLES -std=c++0x" LIBRARIES ${OPENGLES2_LIBRARIES} ${INTERNAL_LIBRARIES} dl INCDIRS ${OPENGLES2_INCLUDE_DIR})
21
22=== modified file 'plugins/opengl/include/opengl/doublebuffer.h'
23--- plugins/opengl/include/opengl/doublebuffer.h 2012-09-12 03:55:21 +0000
24+++ plugins/opengl/include/opengl/doublebuffer.h 2012-09-22 03:12:18 +0000
25@@ -2,6 +2,7 @@
26 #define _COMPIZ_OPENGL_BUFFERBLIT_H
27
28 #include <core/region.h>
29+#include <vsyncmethod.h>
30
31 namespace compiz
32 {
33@@ -11,7 +12,7 @@
34 class DoubleBuffer
35 {
36 public:
37- DoubleBuffer ();
38+ DoubleBuffer (const std::list <VSyncMethod::Ptr> &vsyncMethods);
39 virtual ~DoubleBuffer ();
40
41 virtual void swap () const = 0;
42@@ -31,9 +32,17 @@
43
44 void set (Setting name, bool value);
45 void render (const CompRegion &region, bool fullscreen);
46+ void vsync (BufferSwapType swapType);
47+
48+ bool hardwareVSyncFunctional ();
49
50 protected:
51 bool setting[_NSETTINGS];
52+
53+ private:
54+ unsigned int unthrottledFrames;
55+ std::list <VSyncMethod::Ptr> vsyncMethods;
56+ VSyncMethod::Ptr lastSuccessfulVSyncMethod;
57 };
58
59 }
60
61=== modified file 'plugins/opengl/src/doublebuffer/CMakeLists.txt'
62--- plugins/opengl/src/doublebuffer/CMakeLists.txt 2012-07-05 08:17:49 +0000
63+++ plugins/opengl/src/doublebuffer/CMakeLists.txt 2012-09-22 03:12:18 +0000
64@@ -1,6 +1,7 @@
65 INCLUDE_DIRECTORIES (
66 ${compiz_SOURCE_DIR}/src/logmessage/include
67 ${CMAKE_CURRENT_SOURCE_DIR}/../../include
68+ ${CMAKE_CURRENT_SOURCE_DIR}/../../src
69 ${CMAKE_CURRENT_SOURCE_DIR}/src
70
71 ${Boost_INCLUDE_DIRS}
72
73=== modified file 'plugins/opengl/src/doublebuffer/src/double-buffer.cpp'
74--- plugins/opengl/src/doublebuffer/src/double-buffer.cpp 2012-09-12 03:55:21 +0000
75+++ plugins/opengl/src/doublebuffer/src/double-buffer.cpp 2012-09-22 03:12:18 +0000
76@@ -38,7 +38,9 @@
77 namespace opengl
78 {
79
80-DoubleBuffer::DoubleBuffer ()
81+DoubleBuffer::DoubleBuffer (const std::list <VSyncMethod::Ptr> &vsyncMethods) :
82+ unthrottledFrames (0),
83+ vsyncMethods (vsyncMethods)
84 {
85 setting[VSYNC] = true;
86 setting[HAVE_PERSISTENT_BACK_BUFFER] = false;
87@@ -61,23 +63,74 @@
88 {
89 if (fullscreen)
90 {
91+ if (setting[VSYNC])
92+ vsync (Flip);
93+
94 swap ();
95+
96 if (setting[NEED_PERSISTENT_BACK_BUFFER] &&
97 !setting[HAVE_PERSISTENT_BACK_BUFFER])
98 {
99 copyFrontToBack ();
100 }
101 }
102- else if (blitAvailable ())
103- blit (region);
104- else if (fallbackBlitAvailable ())
105- fallbackBlit (region);
106- else
107- {
108- // This will never happen unless you make a porting mistake...
109- assert (false);
110- abort ();
111- }
112+ else
113+ {
114+ if (setting[VSYNC])
115+ vsync (PartialCopy);
116+
117+ if (blitAvailable ())
118+ blit (region);
119+ else if (fallbackBlitAvailable ())
120+ fallbackBlit (region);
121+ else
122+ {
123+ // This will never happen unless you make a porting mistake...
124+ assert (false);
125+ abort ();
126+ }
127+ }
128+}
129+
130+void
131+DoubleBuffer::vsync (BufferSwapType swapType)
132+{
133+ bool throttled = true;
134+
135+ for (std::list <VSyncMethod::Ptr>::iterator it = vsyncMethods.begin ();
136+ it != vsyncMethods.end ();
137+ ++it)
138+ {
139+ VSyncMethod::Ptr &method (*it);
140+
141+ /* Try and use this method, check if this method
142+ * throttled us too */
143+ if (method->enableForBufferSwapType (swapType, throttled))
144+ {
145+ if (lastSuccessfulVSyncMethod &&
146+ lastSuccessfulVSyncMethod != method)
147+ lastSuccessfulVSyncMethod->disable ();
148+
149+ lastSuccessfulVSyncMethod = method;
150+ break;
151+ }
152+ else
153+ {
154+ throttled = false;
155+ method->disable ();
156+ }
157+ }
158+
159+ if (!throttled)
160+ unthrottledFrames++;
161+ else
162+ unthrottledFrames = 0;
163+}
164+
165+bool
166+DoubleBuffer::hardwareVSyncFunctional ()
167+{
168+ return unthrottledFrames < 5;
169 }
170
171 } // namespace opengl
172
173=== modified file 'plugins/opengl/src/doublebuffer/tests/test-opengl-double-buffer.cpp'
174--- plugins/opengl/src/doublebuffer/tests/test-opengl-double-buffer.cpp 2012-09-12 10:45:58 +0000
175+++ plugins/opengl/src/doublebuffer/tests/test-opengl-double-buffer.cpp 2012-09-22 03:12:18 +0000
176@@ -2,17 +2,24 @@
177 #include <gmock/gmock.h>
178
179 #include <opengl/doublebuffer.h>
180+#include <vsyncmethod.h>
181
182 using namespace compiz::opengl;
183 using testing::_;
184 using testing::StrictMock;
185 using testing::Return;
186+using testing::SetArgReferee;
187
188 class MockDoubleBuffer :
189 public DoubleBuffer
190 {
191 public:
192
193+ MockDoubleBuffer (const std::list <VSyncMethod::Ptr> &vsyncMethods) :
194+ DoubleBuffer (vsyncMethods)
195+ {
196+ }
197+
198 MOCK_CONST_METHOD0 (swap, void ());
199 MOCK_CONST_METHOD0 (blitAvailable, bool ());
200 MOCK_CONST_METHOD1 (blit, void (const CompRegion &));
201@@ -21,13 +28,28 @@
202 MOCK_CONST_METHOD0 (copyFrontToBack, void ());
203 };
204
205+class MockVSyncMethod :
206+ public VSyncMethod
207+{
208+ public:
209+
210+ MOCK_METHOD2 (enableForBufferSwapType, bool (BufferSwapType, bool &));
211+ MOCK_METHOD0 (disable, void ());
212+};
213+
214 class DoubleBufferTest :
215 public ::testing::Test
216 {
217 public:
218
219- MockDoubleBuffer db;
220- CompRegion blitRegion;
221+ DoubleBufferTest () :
222+ db (vsyncMethods)
223+ {
224+ }
225+
226+ std::list <VSyncMethod::Ptr> vsyncMethods;
227+ MockDoubleBuffer db;
228+ CompRegion blitRegion;
229
230 };
231
232@@ -102,7 +124,8 @@
233
234 TEST_F(CompizOpenGLDoubleBufferDeathTest, TestNoPaintedFullscreenOrFBODoesNotBlitOrCopyIfNotSupportedAndDies)
235 {
236- StrictMock <MockDoubleBuffer> dbStrict;
237+ std::list <VSyncMethod::Ptr> vsyncMethods;
238+ StrictMock <MockDoubleBuffer> dbStrict (vsyncMethods);
239
240 ON_CALL (dbStrict, blitAvailable ()).WillByDefault (Return (false));
241 ON_CALL (dbStrict, fallbackBlitAvailable ()).WillByDefault (Return (false));
242@@ -115,7 +138,8 @@
243
244 TEST_F(DoubleBufferTest, TestSubBufferCopyIfNoFBOAndNoSubBufferBlit)
245 {
246- StrictMock <MockDoubleBuffer> dbStrict;
247+ std::list <VSyncMethod::Ptr> vsyncMethods;
248+ StrictMock <MockDoubleBuffer> dbStrict (vsyncMethods);
249
250 EXPECT_CALL (dbStrict, blitAvailable ()).WillOnce (Return (false));
251 EXPECT_CALL (dbStrict, fallbackBlitAvailable ()).WillOnce (Return (true));
252@@ -123,3 +147,141 @@
253
254 dbStrict.render (blitRegion, false);
255 }
256+
257+TEST (DoubleBufferVSyncTest, TestCallWorkingStrategy)
258+{
259+ boost::shared_ptr <MockVSyncMethod> mockVSyncMethod (new MockVSyncMethod ());
260+ std::list <VSyncMethod::Ptr> vsyncMethods;
261+
262+ vsyncMethods.push_back (mockVSyncMethod);
263+
264+ MockDoubleBuffer doubleBuffer (vsyncMethods);
265+
266+ EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (Flip, _))
267+ .WillOnce (Return (true));
268+
269+ doubleBuffer.vsync (Flip);
270+}
271+
272+TEST (DoubleBufferVSyncTest, TestCallNextWorkingStrategy)
273+{
274+ boost::shared_ptr <MockVSyncMethod> mockVSyncMethod (new MockVSyncMethod ());
275+ boost::shared_ptr <MockVSyncMethod> mockVSyncMethodSafer (new MockVSyncMethod ());
276+ std::list <VSyncMethod::Ptr> vsyncMethods;
277+
278+ vsyncMethods.push_back (mockVSyncMethod);
279+ vsyncMethods.push_back (mockVSyncMethodSafer);
280+
281+ MockDoubleBuffer doubleBuffer (vsyncMethods);
282+
283+ /* This one fails */
284+ EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
285+ .WillOnce (Return (false));
286+ /* It needs to be deactivated */
287+ EXPECT_CALL (*mockVSyncMethod, disable ());
288+ /* Try the next one */
289+ EXPECT_CALL (*mockVSyncMethodSafer, enableForBufferSwapType (PartialCopy, _))
290+ .WillOnce (Return (true));
291+
292+ doubleBuffer.vsync (PartialCopy);
293+}
294+
295+TEST (DoubleBufferVSyncTest, TestCallPrevCallNextPrevDeactivated)
296+{
297+ boost::shared_ptr <MockVSyncMethod> mockVSyncMethod (new MockVSyncMethod ());
298+ boost::shared_ptr <MockVSyncMethod> mockVSyncMethodSafer (new MockVSyncMethod ());
299+ std::list <VSyncMethod::Ptr> vsyncMethods;
300+
301+ vsyncMethods.push_back (mockVSyncMethod);
302+ vsyncMethods.push_back (mockVSyncMethodSafer);
303+
304+ MockDoubleBuffer doubleBuffer (vsyncMethods);
305+
306+ /* This one fails */
307+ EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
308+ .WillOnce (Return (false));
309+ /* It needs to be deactivated */
310+ EXPECT_CALL (*mockVSyncMethod, disable ());
311+ /* Try the next one */
312+ EXPECT_CALL (*mockVSyncMethodSafer, enableForBufferSwapType (PartialCopy, _))
313+ .WillOnce (Return (true));
314+
315+ doubleBuffer.vsync (PartialCopy);
316+
317+ /* Now the previous one works */
318+ EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
319+ .WillOnce (Return (true));
320+ /* Previous one must be deactivated */
321+ EXPECT_CALL (*mockVSyncMethodSafer, disable ());
322+
323+ doubleBuffer.vsync (PartialCopy);
324+}
325+
326+TEST (DoubleBufferVSyncTest, TestReportNoHardwareVSyncIfMoreThan5UnthrottledFrames)
327+{
328+ boost::shared_ptr <MockVSyncMethod> mockVSyncMethod (new MockVSyncMethod ());
329+ std::list <VSyncMethod::Ptr> vsyncMethods;
330+
331+ vsyncMethods.push_back (mockVSyncMethod);
332+
333+ /* Always succeed */
334+ ON_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _)).WillByDefault (Return (true));
335+
336+ MockDoubleBuffer doubleBuffer (vsyncMethods);
337+
338+ /* This one succeeds but fails to throttle */
339+ for (unsigned int i = 0; i < 5; ++i)
340+ {
341+ EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
342+ .WillOnce (SetArgReferee <1> (false));
343+
344+ doubleBuffer.vsync (PartialCopy);
345+ }
346+
347+ EXPECT_FALSE (doubleBuffer.hardwareVSyncFunctional ());
348+}
349+
350+TEST (DoubleBufferVSyncTest, TestRestoreReportHardwareVSync)
351+{
352+ boost::shared_ptr <MockVSyncMethod> mockVSyncMethod (new MockVSyncMethod ());
353+ std::list <VSyncMethod::Ptr> vsyncMethods;
354+
355+ vsyncMethods.push_back (mockVSyncMethod);
356+
357+ MockDoubleBuffer doubleBuffer (vsyncMethods);
358+
359+ /* Always succeed */
360+ ON_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _)).WillByDefault (Return (true));
361+
362+ /* This one succeeds but fails to throttle */
363+ for (unsigned int i = 0; i < 5; ++i)
364+ {
365+ EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
366+ .WillOnce (SetArgReferee <1> (false));
367+
368+ EXPECT_TRUE (doubleBuffer.hardwareVSyncFunctional ());
369+
370+ doubleBuffer.vsync (PartialCopy);
371+ }
372+
373+ EXPECT_FALSE (doubleBuffer.hardwareVSyncFunctional ());
374+
375+ /* It works again */
376+ EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
377+ .WillOnce (SetArgReferee <1> (true));
378+
379+ doubleBuffer.vsync (PartialCopy);
380+
381+ /* And should report to work for another 5 bad frames */
382+ for (unsigned int i = 0; i < 5; ++i)
383+ {
384+ EXPECT_CALL (*mockVSyncMethod, enableForBufferSwapType (PartialCopy, _))
385+ .WillOnce (SetArgReferee <1> (false));
386+
387+ EXPECT_TRUE (doubleBuffer.hardwareVSyncFunctional ());
388+
389+ doubleBuffer.vsync (PartialCopy);
390+ }
391+
392+ EXPECT_FALSE (doubleBuffer.hardwareVSyncFunctional ());
393+}
394
395=== modified file 'plugins/opengl/src/privates.h'
396--- plugins/opengl/src/privates.h 2012-09-20 09:35:40 +0000
397+++ plugins/opengl/src/privates.h 2012-09-22 03:12:18 +0000
398@@ -28,6 +28,8 @@
399 #ifndef _OPENGL_PRIVATES_H
400 #define _OPENGL_PRIVATES_H
401
402+#include <memory>
403+
404 #include <composite/composite.h>
405 #include <opengl/opengl.h>
406 #include <core/atoms.h>
407@@ -44,13 +46,23 @@
408
409 extern CompOutput *targetOutput;
410
411+namespace compiz
412+{
413+ namespace opengl
414+ {
415+ class VSyncMethod;
416+ typedef boost::shared_ptr <VSyncMethod> VSyncMethodPtr;
417+ }
418+}
419+
420 class GLDoubleBuffer :
421 public compiz::opengl::DoubleBuffer
422 {
423 public:
424
425- GLDoubleBuffer (Display *,
426- const CompSize &);
427+ GLDoubleBuffer (Display *,
428+ const CompSize &,
429+ const std::list <compiz::opengl::VSyncMethodPtr> &vsyncMethods);
430
431 protected:
432
433@@ -65,9 +77,10 @@
434 {
435 public:
436
437- GLXDoubleBuffer (Display *,
438- const CompSize &,
439- Window);
440+ GLXDoubleBuffer (Display *,
441+ const CompSize &,
442+ Window ,
443+ const std::list <compiz::opengl::VSyncMethodPtr> &vsyncMethods);
444
445 void swap () const;
446 bool blitAvailable () const;
447@@ -88,9 +101,10 @@
448 {
449 public:
450
451- EGLDoubleBuffer (Display *,
452- const CompSize &,
453- EGLSurface const &);
454+ EGLDoubleBuffer (Display *,
455+ const CompSize &,
456+ EGLSurface const &,
457+ const std::list <compiz::opengl::VSyncMethodPtr> &vsyncMethods);
458
459 void swap () const;
460 bool blitAvailable () const;
461@@ -181,12 +195,12 @@
462 #ifdef USE_GLES
463 EGLContext ctx;
464 EGLSurface surface;
465- EGLDoubleBuffer doubleBuffer;
466+ std::auto_ptr <EGLDoubleBuffer> doubleBuffer;
467 #else
468 GLXContext ctx;
469
470 GL::GLXGetProcAddressProc getProcAddress;
471- GLXDoubleBuffer doubleBuffer;
472+ std::auto_ptr <GLXDoubleBuffer> doubleBuffer;
473 #endif
474
475 GLFramebufferObject *scratchFbo;
476
477=== modified file 'plugins/opengl/src/screen.cpp'
478--- plugins/opengl/src/screen.cpp 2012-09-20 09:35:40 +0000
479+++ plugins/opengl/src/screen.cpp 2012-09-22 03:12:18 +0000
480@@ -32,7 +32,13 @@
481 #endif
482 #include <errno.h>
483
484+#include <boost/bind.hpp>
485+#include <boost/make_shared.hpp>
486+
487 #include "privates.h"
488+#include "vsyncmethod.h"
489+#include "vsync-method-swap-interval.h"
490+#include "vsync-method-wait-video-sync.h"
491
492 #include <dlfcn.h>
493 #include <math.h>
494@@ -162,7 +168,6 @@
495 bool canDoSlightlySaturated = false;
496
497 unsigned int vsyncCount = 0;
498- unsigned int unthrottledFrames = 0;
499
500 bool stencilBuffer = false;
501 #ifndef USE_GLES
502@@ -271,9 +276,70 @@
503 GLScreen *gScreen;
504 };
505
506+#ifndef USE_GLES
507+
508+namespace compiz
509+{
510+ namespace opengl
511+ {
512+ void swapIntervalGLX (int interval)
513+ {
514+ // Docs: http://www.opengl.org/registry/specs/SGI/swap_control.txt
515+ if (GL::swapInterval)
516+ (*GL::swapInterval) (interval);
517+ }
518+
519+ int waitVSyncGLX (int wait,
520+ int remainder,
521+ unsigned int *count)
522+ {
523+ /*
524+ * While glXSwapBuffers/glXCopySubBufferMESA are meant to do a
525+ * flush before they blit, it is best to not let that happen.
526+ * Because that flush would occur after GL::waitVideoSync, causing
527+ * a delay and the final blit to be slightly out of sync resulting
528+ * in tearing. So we need to do a glFinish before we wait for
529+ * vsync, to absolutely minimize tearing.
530+ */
531+ glFinish ();
532+
533+ // Docs: http://www.opengl.org/registry/specs/SGI/video_sync.txt
534+ if (GL::waitVideoSync)
535+ return (*GL::waitVideoSync) (wait, remainder, count);
536+
537+ return 0;
538+ }
539+ }
540+}
541+
542+#else
543+
544+namespace compiz
545+{
546+ namespace opengl
547+ {
548+ void swapIntervalEGL (Display *display, int interval)
549+ {
550+ eglSwapInterval (eglGetDisplay (display), interval);
551+ }
552+
553+ int waitVSyncEGL (int wait,
554+ int remainder,
555+ int *count)
556+ {
557+ /* not supported */
558+ return 0;
559+ }
560+ }
561+}
562+
563+#endif
564+
565 bool
566 GLScreen::glInitContext (XVisualInfo *visinfo)
567 {
568+ std::list <compiz::opengl::VSyncMethod::Ptr> availableVSyncMethods;
569+
570 #ifdef USE_GLES
571 Display *xdpy;
572 Window overlay;
573@@ -497,6 +563,14 @@
574 priv->filter[SCREEN_TRANS_FILTER] = GLTexture::Good;
575 priv->filter[WINDOW_TRANS_FILTER] = GLTexture::Good;
576
577+ availableVSyncMethods.push_back (boost::make_shared <impl::SwapIntervalVSyncMethod> (
578+ boost::bind (swapIntervalEGL, screen->dpy (), _1)));
579+
580+ priv->doubleBuffer.reset (new EGLDoubleBuffer (screen->dpy (),
581+ *screen,
582+ priv->surface,
583+ availableVSyncMethods));
584+
585 if (GL::textureFromPixmap)
586 registerBindPixmap (EglTexture::bindPixmapToTexture);
587
588@@ -794,6 +868,16 @@
589 priv->filter[SCREEN_TRANS_FILTER] = GLTexture::Good;
590 priv->filter[WINDOW_TRANS_FILTER] = GLTexture::Good;
591
592+ availableVSyncMethods.push_back (boost::make_shared <impl::SwapIntervalVSyncMethod> (
593+ boost::bind (swapIntervalGLX, _1)));
594+ availableVSyncMethods.push_back (boost::make_shared <impl::WaitVSyncMethod> (
595+ boost::bind (waitVSyncGLX, _1, _2, _3)));
596+
597+ priv->doubleBuffer.reset (new GLXDoubleBuffer (screen->dpy (),
598+ *screen,
599+ priv->cScreen->output (),
600+ availableVSyncMethods));
601+
602 if (GL::textureFromPixmap)
603 registerBindPixmap (TfpTexture::bindPixmapToTexture);
604 #endif
605@@ -1120,9 +1204,6 @@
606 lighting (false),
607 #ifndef USE_GLES
608 getProcAddress (0),
609- doubleBuffer (screen->dpy (), *screen, cScreen->output ()),
610- #else
611- doubleBuffer (screen->dpy (), *screen, surface),
612 #endif
613 scratchFbo (NULL),
614 outputRegion (),
615@@ -1670,61 +1751,17 @@
616 return &priv->shaderCache.getShaderData(params);
617 }
618
619+
620+
621 namespace GL
622 {
623
624-void
625-waitForVideoSync ()
626-{
627-#ifndef USE_GLES
628- GL::unthrottledFrames++;
629- if (GL::waitVideoSync)
630- {
631- // Don't wait twice. Just in case.
632- if (GL::swapInterval)
633- (*GL::swapInterval) (0);
634-
635- /*
636- * While glXSwapBuffers/glXCopySubBufferMESA are meant to do a
637- * flush before they blit, it is best to not let that happen.
638- * Because that flush would occur after GL::waitVideoSync, causing
639- * a delay and the final blit to be slightly out of sync resulting
640- * in tearing. So we need to do a glFinish before we wait for
641- * vsync, to absolutely minimize tearing.
642- */
643- glFinish ();
644-
645- // Docs: http://www.opengl.org/registry/specs/SGI/video_sync.txt
646- unsigned int oldCount = GL::vsyncCount;
647- (*GL::waitVideoSync) (1, 0, &GL::vsyncCount);
648-
649- if (GL::vsyncCount != oldCount)
650- GL::unthrottledFrames = 0;
651- }
652-#endif
653-}
654-
655-void
656-controlSwapVideoSync (bool sync)
657-{
658-#ifndef USE_GLES
659- // Docs: http://www.opengl.org/registry/specs/SGI/swap_control.txt
660- if (GL::swapInterval)
661- {
662- (*GL::swapInterval) (sync ? 1 : 0);
663- GL::unthrottledFrames++;
664- }
665- else if (sync)
666- waitForVideoSync ();
667-#else
668- eglSwapInterval (eglGetDisplay (screen->dpy ()), sync ? 1 : 0);
669- GL::unthrottledFrames++;
670-#endif
671-}
672-
673 } // namespace GL
674
675-GLDoubleBuffer::GLDoubleBuffer (Display *d, const CompSize &s) :
676+GLDoubleBuffer::GLDoubleBuffer (Display *d,
677+ const CompSize &s,
678+ const std::list <VSyncMethod::Ptr> &vsyncMethods) :
679+ compiz::opengl::DoubleBuffer (vsyncMethods),
680 mDpy (d),
681 mSize (s)
682 {
683@@ -1757,10 +1794,11 @@
684 glMatrixMode (GL_MODELVIEW);
685 }
686
687-GLXDoubleBuffer::GLXDoubleBuffer (Display *d,
688- const CompSize &s,
689- Window output) :
690- GLDoubleBuffer (d, s),
691+GLXDoubleBuffer::GLXDoubleBuffer (Display *d,
692+ const CompSize &s,
693+ Window output,
694+ const std::list <VSyncMethodPtr> &vsyncMethods) :
695+ GLDoubleBuffer (d, s, vsyncMethods),
696 mOutput (output)
697 {
698 }
699@@ -1768,8 +1806,6 @@
700 void
701 GLXDoubleBuffer::swap () const
702 {
703- GL::controlSwapVideoSync (setting[VSYNC]);
704-
705 glXSwapBuffers (mDpy, mOutput);
706 }
707
708@@ -1784,9 +1820,6 @@
709 {
710 const CompRect::vector &blitRects (region.rects ());
711
712- if (setting[VSYNC])
713- GL::waitForVideoSync ();
714-
715 foreach (const CompRect &r, blitRects)
716 {
717 int y = mSize.height () - r.y2 ();
718@@ -1808,9 +1841,6 @@
719 int w = screen->width ();
720 int h = screen->height ();
721
722- if (setting[VSYNC])
723- GL::waitForVideoSync ();
724-
725 glMatrixMode (GL_PROJECTION);
726 glPushMatrix ();
727 glLoadIdentity ();
728@@ -1840,10 +1870,11 @@
729
730 #else
731
732-EGLDoubleBuffer::EGLDoubleBuffer (Display *d,
733- const CompSize &s,
734- EGLSurface const & surface) :
735- GLDoubleBuffer (d, s),
736+EGLDoubleBuffer::EGLDoubleBuffer (Display *d,
737+ const CompSize &s,
738+ EGLSurface const &surface,
739+ const std::list <VSyncMethodPtr> &vsyncMethods) :
740+ GLDoubleBuffer (d, s, vsyncMethods),
741 mSurface (surface)
742 {
743 }
744@@ -1851,8 +1882,6 @@
745 void
746 EGLDoubleBuffer::swap () const
747 {
748- GL::controlSwapVideoSync (setting[VSYNC]);
749-
750 eglSwapBuffers (eglGetDisplay (mDpy), mSurface);
751 eglWaitGL ();
752 XFlush (mDpy);
753@@ -1870,8 +1899,6 @@
754 CompRect::vector blitRects (region.rects ());
755 int y = 0;
756
757- GL::controlSwapVideoSync (setting[VSYNC]);
758-
759 foreach (const CompRect &r, blitRects)
760 {
761 y = mSize.height () - r.y2 ();
762@@ -2052,10 +2079,10 @@
763 ((mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) &&
764 commonFrontbuffer);
765
766- doubleBuffer.set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());
767- doubleBuffer.set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);
768- doubleBuffer.set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);
769- doubleBuffer.render (tmpRegion, fullscreen);
770+ doubleBuffer->set (DoubleBuffer::VSYNC, optionGetSyncToVblank ());
771+ doubleBuffer->set (DoubleBuffer::HAVE_PERSISTENT_BACK_BUFFER, useFbo);
772+ doubleBuffer->set (DoubleBuffer::NEED_PERSISTENT_BACK_BUFFER, alwaysSwap);
773+ doubleBuffer->render (tmpRegion, fullscreen);
774
775 lastMask = mask;
776 }
777@@ -2066,8 +2093,8 @@
778 #ifdef USE_GLES
779 return false;
780 #else
781- return GL::waitVideoSync && optionGetSyncToVblank () &&
782- GL::unthrottledFrames < 5;
783+ return GL::waitVideoSync && optionGetSyncToVblank () &&
784+ doubleBuffer->hardwareVSyncFunctional ();
785 #endif
786 }
787
788
789=== added directory 'plugins/opengl/src/vsyncmethod'
790=== added file 'plugins/opengl/src/vsyncmethod.h'
791--- plugins/opengl/src/vsyncmethod.h 1970-01-01 00:00:00 +0000
792+++ plugins/opengl/src/vsyncmethod.h 2012-09-22 03:12:18 +0000
793@@ -0,0 +1,61 @@
794+/*
795+ * Compiz, opengl plugin, vsync methods
796+ *
797+ * Copyright © 2012 Canonical Ltd.
798+ * Copyright © 2008 Dennis Kasprzyk
799+ * Copyright © 2007 Novell, Inc.
800+ *
801+ * Permission to use, copy, modify, distribute, and sell this software
802+ * and its documentation for any purpose is hereby granted without
803+ * fee, provided that the above copyright notice appear in all copies
804+ * and that both that copyright notice and this permission notice
805+ * appear in supporting documentation, and that the name of
806+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
807+ * distribution of the software without specific, written prior permission.
808+ * Dennis Kasprzyk makes no representations about the suitability of this
809+ * software for any purpose. It is provided "as is" without express or
810+ * implied warranty.
811+ *
812+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
813+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
814+ * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
815+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
816+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
817+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
818+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
819+ *
820+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
821+ * David Reveman <davidr@novell.com>
822+ * Daniel van Vugt <daniel.van.vugt@canonical.com>
823+ * Sam Spilsbury <sam.spilsbury@canonical.com>
824+ */
825+#ifndef _COMPIZ_OPENGL_VSYNC_METHOD_H
826+#define _COMPIZ_OPENGL_VSYNC_METHOD_H
827+
828+#include <boost/shared_ptr.hpp>
829+
830+namespace compiz
831+{
832+ namespace opengl
833+ {
834+ typedef enum _BufferSwapType
835+ {
836+ Flip,
837+ PartialCopy
838+ } BufferSwapType;
839+
840+ class VSyncMethod
841+ {
842+ public:
843+
844+ typedef boost::shared_ptr <VSyncMethod> Ptr;
845+
846+ virtual bool enableForBufferSwapType (BufferSwapType type,
847+ bool &throttledFrame) = 0;
848+ virtual void disable () = 0;
849+ };
850+ }
851+}
852+
853+#endif
854+
855
856=== added file 'plugins/opengl/src/vsyncmethod/CMakeLists.txt'
857--- plugins/opengl/src/vsyncmethod/CMakeLists.txt 1970-01-01 00:00:00 +0000
858+++ plugins/opengl/src/vsyncmethod/CMakeLists.txt 2012-09-22 03:12:18 +0000
859@@ -0,0 +1,25 @@
860+INCLUDE_DIRECTORIES (
861+ ${CMAKE_CURRENT_SOURCE_DIR}/../../src
862+ ${CMAKE_CURRENT_SOURCE_DIR}/include
863+ ${CMAKE_CURRENT_SOURCE_DIR}/src
864+
865+ ${Boost_INCLUDE_DIRS}
866+)
867+
868+LINK_DIRECTORIES (${COMPIZ_LIBRARY_DIRS})
869+
870+SET(
871+ SRCS
872+ ${CMAKE_CURRENT_SOURCE_DIR}/src/vsync-method-swap-interval.cpp
873+ ${CMAKE_CURRENT_SOURCE_DIR}/src/vsync-method-wait-video-sync.cpp
874+)
875+
876+ADD_LIBRARY(
877+ compiz_opengl_vsync_methods STATIC
878+
879+ ${SRCS}
880+)
881+
882+if (COMPIZ_BUILD_TESTING)
883+ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
884+endif (COMPIZ_BUILD_TESTING)
885
886=== added directory 'plugins/opengl/src/vsyncmethod/include'
887=== added file 'plugins/opengl/src/vsyncmethod/include/vsync-method-swap-interval.h'
888--- plugins/opengl/src/vsyncmethod/include/vsync-method-swap-interval.h 1970-01-01 00:00:00 +0000
889+++ plugins/opengl/src/vsyncmethod/include/vsync-method-swap-interval.h 2012-09-22 03:12:18 +0000
890@@ -0,0 +1,67 @@
891+/*
892+ * Compiz, opengl plugin, vsync methods
893+ *
894+ * Copyright © 2012 Canonical Ltd.
895+ * Copyright © 2008 Dennis Kasprzyk
896+ * Copyright © 2007 Novell, Inc.
897+ *
898+ * Permission to use, copy, modify, distribute, and sell this software
899+ * and its documentation for any purpose is hereby granted without
900+ * fee, provided that the above copyright notice appear in all copies
901+ * and that both that copyright notice and this permission notice
902+ * appear in supporting documentation, and that the name of
903+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
904+ * distribution of the software without specific, written prior permission.
905+ * Dennis Kasprzyk makes no representations about the suitability of this
906+ * software for any purpose. It is provided "as is" without express or
907+ * implied warranty.
908+ *
909+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
910+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
911+ * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
912+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
913+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
914+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
915+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
916+ *
917+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
918+ * David Reveman <davidr@novell.com>
919+ * Daniel van Vugt <daniel.van.vugt@canonical.com>
920+ * Sam Spilsbury <sam.spilsbury@canonical.com>
921+ */
922+#ifndef _COMPIZ_OPENGL_VSYNC_METHOD_SWAP_INTERVAL_H
923+#define _COMPIZ_OPENGL_VSYNC_METHOD_SWAP_INTERVAL_H
924+
925+#include <memory>
926+#include <boost/function.hpp>
927+#include <vsyncmethod.h>
928+
929+namespace compiz
930+{
931+ namespace opengl
932+ {
933+ namespace impl
934+ {
935+ namespace cgl = compiz::opengl;
936+ typedef boost::function <void (int)> GLXSwapIntervalEXTFunc;
937+
938+ class PrivateSwapIntervalVSyncMethod;
939+ class SwapIntervalVSyncMethod :
940+ public cgl::VSyncMethod
941+ {
942+ public:
943+
944+ SwapIntervalVSyncMethod (const GLXSwapIntervalEXTFunc &swapIntervalEXT);
945+
946+ bool enableForBufferSwapType (cgl::BufferSwapType type,
947+ bool &throttledFrame);
948+ void disable ();
949+
950+ private:
951+
952+ std::auto_ptr <PrivateSwapIntervalVSyncMethod> priv;
953+ };
954+ }
955+ } // namespace opengl
956+} // namespace compiz
957+#endif
958
959=== added file 'plugins/opengl/src/vsyncmethod/include/vsync-method-wait-video-sync.h'
960--- plugins/opengl/src/vsyncmethod/include/vsync-method-wait-video-sync.h 1970-01-01 00:00:00 +0000
961+++ plugins/opengl/src/vsyncmethod/include/vsync-method-wait-video-sync.h 2012-09-22 03:12:18 +0000
962@@ -0,0 +1,67 @@
963+/*
964+ * Compiz, opengl plugin, vsync methods
965+ *
966+ * Copyright © 2012 Canonical Ltd.
967+ * Copyright © 2008 Dennis Kasprzyk
968+ * Copyright © 2007 Novell, Inc.
969+ *
970+ * Permission to use, copy, modify, distribute, and sell this software
971+ * and its documentation for any purpose is hereby granted without
972+ * fee, provided that the above copyright notice appear in all copies
973+ * and that both that copyright notice and this permission notice
974+ * appear in supporting documentation, and that the name of
975+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
976+ * distribution of the software without specific, written prior permission.
977+ * Dennis Kasprzyk makes no representations about the suitability of this
978+ * software for any purpose. It is provided "as is" without express or
979+ * implied warranty.
980+ *
981+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
982+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
983+ * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
984+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
985+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
986+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
987+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
988+ *
989+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
990+ * David Reveman <davidr@novell.com>
991+ * Daniel van Vugt <daniel.van.vugt@canonical.com>
992+ * Sam Spilsbury <sam.spilsbury@canonical.com>
993+ */
994+#ifndef _COMPIZ_OPENGL_VSYNC_METHOD_WAIT_VIDEO_SYNC_H
995+#define _COMPIZ_OPENGL_VSYNC_METHOD_WAIT_VIDEO_SYNC_H
996+
997+#include <memory>
998+#include <boost/function.hpp>
999+#include <vsyncmethod.h>
1000+
1001+namespace compiz
1002+{
1003+ namespace opengl
1004+ {
1005+ namespace impl
1006+ {
1007+ namespace cgl = compiz::opengl;
1008+ typedef boost::function <int (int, int, unsigned int *)> GLXWaitVideoSyncSGIFunc;
1009+
1010+ class PrivateWaitVSyncMethod;
1011+ class WaitVSyncMethod :
1012+ public cgl::VSyncMethod
1013+ {
1014+ public:
1015+
1016+ WaitVSyncMethod (const GLXWaitVideoSyncSGIFunc &);
1017+
1018+ bool enableForBufferSwapType (cgl::BufferSwapType type,
1019+ bool &throttledFrame);
1020+ void disable ();
1021+
1022+ private:
1023+
1024+ std::auto_ptr <PrivateWaitVSyncMethod> priv;
1025+ };
1026+ }
1027+ } // namespace opengl
1028+} // namespace compiz
1029+#endif
1030
1031=== added directory 'plugins/opengl/src/vsyncmethod/src'
1032=== added file 'plugins/opengl/src/vsyncmethod/src/vsync-method-swap-interval.cpp'
1033--- plugins/opengl/src/vsyncmethod/src/vsync-method-swap-interval.cpp 1970-01-01 00:00:00 +0000
1034+++ plugins/opengl/src/vsyncmethod/src/vsync-method-swap-interval.cpp 2012-09-22 03:12:18 +0000
1035@@ -0,0 +1,100 @@
1036+/*
1037+ * Compiz, opengl plugin, vsync methods
1038+ *
1039+ * Copyright © 2012 Canonical Ltd.
1040+ * Copyright © 2008 Dennis Kasprzyk
1041+ * Copyright © 2007 Novell, Inc.
1042+ *
1043+ * Permission to use, copy, modify, distribute, and sell this software
1044+ * and its documentation for any purpose is hereby granted without
1045+ * fee, provided that the above copyright notice appear in all copies
1046+ * and that both that copyright notice and this permission notice
1047+ * appear in supporting documentation, and that the name of
1048+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
1049+ * distribution of the software without specific, written prior permission.
1050+ * Dennis Kasprzyk makes no representations about the suitability of this
1051+ * software for any purpose. It is provided "as is" without express or
1052+ * implied warranty.
1053+ *
1054+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1055+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
1056+ * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1057+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
1058+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
1059+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
1060+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1061+ *
1062+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
1063+ * David Reveman <davidr@novell.com>
1064+ * Daniel van Vugt <daniel.van.vugt@canonical.com>
1065+ * Sam Spilsbury <sam.spilsbury@canonical.com>
1066+ */
1067+#include <vsyncmethod.h>
1068+#include <vsync-method-swap-interval.h>
1069+
1070+namespace compiz
1071+{
1072+ namespace opengl
1073+ {
1074+ namespace impl
1075+ {
1076+ class PrivateSwapIntervalVSyncMethod
1077+ {
1078+ public:
1079+
1080+ PrivateSwapIntervalVSyncMethod (const GLXSwapIntervalEXTFunc &);
1081+
1082+ GLXSwapIntervalEXTFunc swapInterval;
1083+ bool enabled;
1084+ };
1085+ }
1086+ }
1087+}
1088+
1089+namespace cgl = compiz::opengl;
1090+namespace cgli = compiz::opengl::impl;
1091+
1092+cgli::PrivateSwapIntervalVSyncMethod::PrivateSwapIntervalVSyncMethod (const GLXSwapIntervalEXTFunc &swapInterval) :
1093+ swapInterval (swapInterval),
1094+ enabled (false)
1095+{
1096+}
1097+
1098+cgli::SwapIntervalVSyncMethod::SwapIntervalVSyncMethod (const GLXSwapIntervalEXTFunc &swapInterval) :
1099+ priv (new cgli::PrivateSwapIntervalVSyncMethod (swapInterval))
1100+{
1101+
1102+}
1103+
1104+bool
1105+cgli::SwapIntervalVSyncMethod::enableForBufferSwapType (cgl::BufferSwapType swapType,
1106+ bool &throttledFrame)
1107+{
1108+ /* Always consider these frames as un-throttled as the buffer
1109+ * swaps are done asynchronously */
1110+ throttledFrame = false;
1111+
1112+ /* Can't use swapInterval unless using SwapBuffers */
1113+ if (swapType != cgl::Flip)
1114+ return false;
1115+
1116+ /* Enable if not enabled */
1117+ if (!priv->enabled)
1118+ {
1119+ priv->swapInterval (1);
1120+ priv->enabled = true;
1121+ }
1122+
1123+ return true;
1124+}
1125+
1126+void
1127+cgli::SwapIntervalVSyncMethod::disable ()
1128+{
1129+ /* Disable if enabled */
1130+ if (priv->enabled)
1131+ {
1132+ priv->swapInterval (0);
1133+ priv->enabled = false;
1134+ }
1135+}
1136
1137=== added file 'plugins/opengl/src/vsyncmethod/src/vsync-method-wait-video-sync.cpp'
1138--- plugins/opengl/src/vsyncmethod/src/vsync-method-wait-video-sync.cpp 1970-01-01 00:00:00 +0000
1139+++ plugins/opengl/src/vsyncmethod/src/vsync-method-wait-video-sync.cpp 2012-09-22 03:12:18 +0000
1140@@ -0,0 +1,87 @@
1141+/*
1142+ * Compiz, opengl plugin, vsync methods
1143+ *
1144+ * Copyright © 2012 Canonical Ltd.
1145+ * Copyright © 2008 Dennis Kasprzyk
1146+ * Copyright © 2007 Novell, Inc.
1147+ *
1148+ * Permission to use, copy, modify, distribute, and sell this software
1149+ * and its documentation for any purpose is hereby granted without
1150+ * fee, provided that the above copyright notice appear in all copies
1151+ * and that both that copyright notice and this permission notice
1152+ * appear in supporting documentation, and that the name of
1153+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
1154+ * distribution of the software without specific, written prior permission.
1155+ * Dennis Kasprzyk makes no representations about the suitability of this
1156+ * software for any purpose. It is provided "as is" without express or
1157+ * implied warranty.
1158+ *
1159+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1160+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
1161+ * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1162+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
1163+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
1164+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
1165+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1166+ *
1167+ * Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
1168+ * David Reveman <davidr@novell.com>
1169+ * Daniel van Vugt <daniel.van.vugt@canonical.com>
1170+ * Sam Spilsbury <sam.spilsbury@canonical.com>
1171+ */
1172+#include <vsyncmethod.h>
1173+#include <vsync-method-wait-video-sync.h>
1174+
1175+namespace compiz
1176+{
1177+ namespace opengl
1178+ {
1179+ namespace impl
1180+ {
1181+ class PrivateWaitVSyncMethod
1182+ {
1183+ public:
1184+
1185+ PrivateWaitVSyncMethod (const GLXWaitVideoSyncSGIFunc &);
1186+
1187+ GLXWaitVideoSyncSGIFunc waitVideoSync;
1188+ unsigned int lastVSyncCounter;
1189+ };
1190+ }
1191+ }
1192+}
1193+
1194+namespace cgl = compiz::opengl;
1195+namespace cgli = compiz::opengl::impl;
1196+
1197+cgli::PrivateWaitVSyncMethod::PrivateWaitVSyncMethod (const cgli::GLXWaitVideoSyncSGIFunc &waitVideoSync) :
1198+ waitVideoSync (waitVideoSync),
1199+ lastVSyncCounter (0)
1200+{
1201+}
1202+
1203+cgli::WaitVSyncMethod::WaitVSyncMethod (const cgli::GLXWaitVideoSyncSGIFunc &waitVideoSync) :
1204+ priv (new cgli::PrivateWaitVSyncMethod (waitVideoSync))
1205+{
1206+}
1207+
1208+bool
1209+cgli::WaitVSyncMethod::enableForBufferSwapType (cgl::BufferSwapType swapType,
1210+ bool &throttledFrame)
1211+{
1212+ unsigned int oldVideoSyncCounter = priv->lastVSyncCounter;
1213+ priv->waitVideoSync (1, 0, &priv->lastVSyncCounter);
1214+
1215+ /* Check if this frame was actually throttled */
1216+ if (priv->lastVSyncCounter == oldVideoSyncCounter)
1217+ throttledFrame = false;
1218+ else
1219+ throttledFrame = true;
1220+
1221+ return true;
1222+}
1223+
1224+void
1225+cgli::WaitVSyncMethod::disable ()
1226+{
1227+}
1228
1229=== added directory 'plugins/opengl/src/vsyncmethod/tests'
1230=== added file 'plugins/opengl/src/vsyncmethod/tests/CMakeLists.txt'
1231--- plugins/opengl/src/vsyncmethod/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
1232+++ plugins/opengl/src/vsyncmethod/tests/CMakeLists.txt 2012-09-22 03:12:18 +0000
1233@@ -0,0 +1,24 @@
1234+find_library (GMOCK_LIBRARY gmock)
1235+find_library (GMOCK_MAIN_LIBRARY gmock_main)
1236+
1237+if (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
1238+ message ("Google Mock and Google Test not found - cannot build tests!")
1239+ set (COMPIZ_BUILD_TESTING OFF)
1240+endif (NOT GMOCK_LIBRARY OR NOT GMOCK_MAIN_LIBRARY OR NOT GTEST_FOUND)
1241+
1242+include_directories (${GTEST_INCLUDE_DIRS})
1243+
1244+link_directories (${COMPIZ_LIBRARY_DIRS})
1245+
1246+add_executable (compiz_test_opengl_vsync_methods
1247+ ${CMAKE_CURRENT_SOURCE_DIR}/test-opengl-vsync-methods.cpp)
1248+
1249+target_link_libraries (compiz_test_opengl_vsync_methods
1250+ compiz_opengl_vsync_methods
1251+ ${GTEST_BOTH_LIBRARIES}
1252+ ${GMOCK_LIBRARY}
1253+ ${GMOCK_MAIN_LIBRARY}
1254+ ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
1255+ )
1256+
1257+compiz_discover_tests (compiz_test_opengl_vsync_methods COVERAGE compiz_opengl_vsync_methods)
1258
1259=== added file 'plugins/opengl/src/vsyncmethod/tests/test-opengl-vsync-methods.cpp'
1260--- plugins/opengl/src/vsyncmethod/tests/test-opengl-vsync-methods.cpp 1970-01-01 00:00:00 +0000
1261+++ plugins/opengl/src/vsyncmethod/tests/test-opengl-vsync-methods.cpp 2012-09-22 03:12:18 +0000
1262@@ -0,0 +1,215 @@
1263+/*
1264+ * Compiz, opengl plugin, vsync methods
1265+ *
1266+ * Copyright © 2012 Canonical Ltd.
1267+ *
1268+ * Permission to use, copy, modify, distribute, and sell this software
1269+ * and its documentation for any purpose is hereby granted without
1270+ * fee, provided that the above copyright notice appear in all copies
1271+ * and that both that copyright notice and this permission notice
1272+ * appear in supporting documentation, and that the name of
1273+ * Dennis Kasprzyk not be used in advertising or publicity pertaining to
1274+ * distribution of the software without specific, written prior permission.
1275+ * Dennis Kasprzyk makes no representations about the suitability of this
1276+ * software for any purpose. It is provided "as is" without express or
1277+ * implied warranty.
1278+ *
1279+ * DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1280+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
1281+ * NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1282+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
1283+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
1284+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
1285+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1286+ *
1287+ * Authors: Sam Spilsbury <sam.spilsbury@canonical.com>
1288+ */
1289+#include <boost/bind.hpp>
1290+
1291+#include <gtest/gtest.h>
1292+#include <gmock/gmock.h>
1293+
1294+#include <vsync-method-wait-video-sync.h>
1295+#include <vsync-method-swap-interval.h>
1296+
1297+namespace cgl = compiz::opengl;
1298+namespace cgli = compiz::opengl::impl;
1299+
1300+using ::testing::Return;
1301+using ::testing::DoAll;
1302+using ::testing::SetArgPointee;
1303+using ::testing::_;
1304+
1305+namespace
1306+{
1307+ class MockOpenGLFunctionsTable
1308+ {
1309+ public:
1310+
1311+ MOCK_METHOD3 (waitVideoSyncSGI, int (int, int, unsigned int *));
1312+ MOCK_METHOD1 (swapIntervalEXT, void (int));
1313+ };
1314+
1315+ cgli::GLXWaitVideoSyncSGIFunc
1316+ GetWaitVideoSyncFuncFromMock (MockOpenGLFunctionsTable &mock)
1317+ {
1318+ return boost::bind (&MockOpenGLFunctionsTable::waitVideoSyncSGI, &mock, _1, _2, _3);
1319+ }
1320+
1321+ cgli::GLXSwapIntervalEXTFunc
1322+ GetSwapIntervalFuncFromMock (MockOpenGLFunctionsTable &mock)
1323+ {
1324+ return boost::bind (&MockOpenGLFunctionsTable::swapIntervalEXT, &mock, _1);
1325+ }
1326+}
1327+
1328+class OpenGLSwapIntervalTest :
1329+ public ::testing::Test
1330+{
1331+ public:
1332+
1333+ OpenGLSwapIntervalTest () :
1334+ swapIntervalMethod (GetSwapIntervalFuncFromMock (functions))
1335+ {
1336+ }
1337+
1338+ MockOpenGLFunctionsTable functions;
1339+ cgli::SwapIntervalVSyncMethod swapIntervalMethod;
1340+};
1341+
1342+class OpenGLWaitVideoSyncTest :
1343+ public ::testing::Test
1344+{
1345+ public:
1346+
1347+ OpenGLWaitVideoSyncTest () :
1348+ waitVideoSyncMethod (GetWaitVideoSyncFuncFromMock (functions))
1349+ {
1350+ }
1351+
1352+ MockOpenGLFunctionsTable functions;
1353+ cgli::WaitVSyncMethod waitVideoSyncMethod;
1354+};
1355+
1356+TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalOnEnableForFlip)
1357+{
1358+ bool throttled;
1359+ EXPECT_CALL (functions, swapIntervalEXT (1));
1360+ EXPECT_TRUE (swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled));
1361+}
1362+
1363+TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalOnEnableForFlipOnlyOnce)
1364+{
1365+ bool throttled;
1366+ EXPECT_CALL (functions, swapIntervalEXT (1)).Times (1);
1367+ EXPECT_TRUE (swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled));
1368+ /* This is still meant to return true even though it does
1369+ * nothing it just means the operation succeeded */
1370+ EXPECT_TRUE (swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled));
1371+}
1372+
1373+TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalOnEnableForFlipAndZeroForDisable)
1374+{
1375+ bool throttled;
1376+ EXPECT_CALL (functions, swapIntervalEXT (1));
1377+ EXPECT_TRUE (swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled));
1378+ EXPECT_CALL (functions, swapIntervalEXT (0));
1379+ swapIntervalMethod.disable ();
1380+}
1381+
1382+TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalZeroForDisableOnce)
1383+{
1384+ bool throttled;
1385+ /* Enable it */
1386+ EXPECT_CALL (functions, swapIntervalEXT (1)).Times (1);
1387+ swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled);
1388+
1389+ /* Disable it twice */
1390+ EXPECT_CALL (functions, swapIntervalEXT (0)).Times (1);
1391+ swapIntervalMethod.disable ();
1392+ swapIntervalMethod.disable ();
1393+}
1394+
1395+TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalFailsToEnableForCopy)
1396+{
1397+ bool throttled;
1398+ EXPECT_FALSE (swapIntervalMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
1399+}
1400+
1401+TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalUnthrottledWhereFailure)
1402+{
1403+ bool throttled;
1404+ EXPECT_FALSE (swapIntervalMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
1405+ EXPECT_FALSE (throttled);
1406+}
1407+
1408+TEST_F (OpenGLSwapIntervalTest, TestSwapIntervalUnthrottledWhereSuccess)
1409+{
1410+ bool throttled;
1411+ EXPECT_TRUE (swapIntervalMethod.enableForBufferSwapType (cgl::Flip, throttled));
1412+ EXPECT_FALSE (throttled);
1413+}
1414+
1415+TEST_F (OpenGLWaitVideoSyncTest, TestCallsGetVideoSyncAndWaitVideoSyncForCopy)
1416+{
1417+ bool throttled;
1418+ EXPECT_CALL (functions, waitVideoSyncSGI (_, _, _));
1419+ EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
1420+}
1421+
1422+TEST_F (OpenGLWaitVideoSyncTest, TestCallsGetVideoSyncAndWaitVideoSyncForFlip)
1423+{
1424+ bool throttled;
1425+ EXPECT_CALL (functions, waitVideoSyncSGI (_, _, _));
1426+ EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::Flip, throttled));
1427+}
1428+
1429+TEST_F (OpenGLWaitVideoSyncTest, TestCallsWaitVideoSyncAndThrottled)
1430+{
1431+ bool throttled = false;
1432+
1433+ /* Frame 0 to frame 1 */
1434+ EXPECT_CALL (functions, waitVideoSyncSGI (1, _, _)).WillOnce (DoAll (SetArgPointee<2> (1),
1435+ Return (0)));
1436+ /* Returned next frame, this frame was throttled */
1437+ EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
1438+ EXPECT_TRUE (throttled);
1439+}
1440+
1441+TEST_F (OpenGLWaitVideoSyncTest, TestCallsWaitVideoSyncAndThrottledEveryFrame)
1442+{
1443+ bool throttled = false;
1444+
1445+ /* Frame 0 to frame 1 */
1446+ EXPECT_CALL (functions, waitVideoSyncSGI (1, 0, _)).WillOnce (DoAll (SetArgPointee<2> (1),
1447+ Return (0)));
1448+ /* Returned next frame, this frame was throttled */
1449+ EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
1450+ EXPECT_TRUE (throttled);
1451+
1452+ /* Frame 1 to frame 2 */
1453+ EXPECT_CALL (functions, waitVideoSyncSGI (1, 0, _)).WillOnce (DoAll (SetArgPointee<2> (2),
1454+ Return (0)));
1455+ /* Returned next frame, this frame was throttled */
1456+ EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
1457+ EXPECT_TRUE (throttled);
1458+}
1459+
1460+TEST_F (OpenGLWaitVideoSyncTest, TestCallsWaitVideoSyncAndUnthrottledDueToBrokenWaitVSync)
1461+{
1462+ bool throttled = false;
1463+
1464+ /* Frame 0 to frame 1 */
1465+ EXPECT_CALL (functions, waitVideoSyncSGI (1, 0, _)).WillOnce (DoAll (SetArgPointee<2> (1),
1466+ Return (0)));
1467+ /* Returned next frame, this frame was throttled */
1468+ EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
1469+ EXPECT_TRUE (throttled);
1470+
1471+ /* Frame 1 to frame 1 (eg, broken waitVideoSyncSGI */
1472+ EXPECT_CALL (functions, waitVideoSyncSGI (1, 0, _)).WillOnce (DoAll (SetArgPointee<2> (1),
1473+ Return (0)));
1474+ /* Returned next frame, this frame was throttled */
1475+ EXPECT_TRUE (waitVideoSyncMethod.enableForBufferSwapType (cgl::PartialCopy, throttled));
1476+ EXPECT_FALSE (throttled);
1477+}

Subscribers

People subscribed via source and target branches