Merge lp:~townsend/compiz/fix-lp269904 into lp:compiz/0.9.12

Proposed by Christopher Townsend
Status: Merged
Approved by: Stephen M. Webb
Approved revision: 3912
Merged at revision: 3916
Proposed branch: lp:~townsend/compiz/fix-lp269904
Merge into: lp:compiz/0.9.12
Diff against target: 819 lines (+622/-5)
8 files modified
debian/changelog (+24/-0)
debian/patches/100_workaround_virtualbox_hang.patch (+4/-4)
plugins/opengl/include/opengl/opengl.h (+64/-0)
plugins/opengl/include/opengl/xtoglsync.h (+99/-0)
plugins/opengl/opengl.xml.in (+5/-0)
plugins/opengl/src/privates.h (+13/-0)
plugins/opengl/src/screen.cpp (+219/-1)
plugins/opengl/src/xtoglsync.cpp (+194/-0)
To merge this branch: bzr merge lp:~townsend/compiz/fix-lp269904
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Stephen M. Webb Approve
Review via email: mp+244149@code.launchpad.net

Commit message

Use the GL_EXT_x11_sync_object OpenGL extension to synchronize updates with X11 to avoid unrefreshed parts of the screen on Nvidia hardware.

To post a comment you must log in.
Revision history for this message
Stephen M. Webb (bregma) wrote :

OK, let's get this egg hatched.

review: Approve
Revision history for this message
Stephen M. Webb (bregma) wrote :

FTBFS on ARM

review: Needs Fixing
lp:~townsend/compiz/fix-lp269904 updated
3911. By Christopher Townsend

Fixed includes to try to fix armhf FTBFS.
Move a updateXToGLSyncs() call to the correct place due to a bad merge.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~townsend/compiz/fix-lp269904 updated
3912. By Christopher Townsend

Move an "#ifndef USE_GLES" after some functions to fix FTBFS on armhf.

Revision history for this message
Stephen M. Webb (bregma) wrote :

Is now fixed, PS Jenkins Bot is late to the party.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2014-12-08 20:58:07 +0000
3+++ debian/changelog 2014-12-10 19:46:40 +0000
4@@ -1,3 +1,27 @@
5+compiz (1:0.9.12.0+15.04.20141120-0ubuntu4) UNRELEASED; urgency=medium
6+
7+ [ James Jones ]
8+ * Added support for GL_EXT_x11_sync_object OpenGL extension for Nvidia
9+ based GPUs to avoid screen refresh issues. (LP: #269904)
10+
11+ [ Kyle Brenneman ]
12+ * Added support for GL_EXT_x11_sync_object OpenGL extension for Nvidia
13+ based GPUs to avoid screen refresh issues. (LP: #269904)
14+
15+ [ Viktor A. Danilov ]
16+ * Added support for GL_EXT_x11_sync_object OpenGL extension for Nvidia
17+ based GPUs to avoid screen refresh issues. (LP: #269904)
18+
19+ [ Chris Townsend ]
20+ * Added support for GL_EXT_x11_sync_object OpenGL extension for Nvidia
21+ based GPUs to avoid screen refresh issues. (LP: #269904)
22+
23+ [ Stephen M. Webb ]
24+ * Added support for GL_EXT_x11_sync_object OpenGL extension for Nvidia
25+ based GPUs to avoid screen refresh issues. (LP: #269904)
26+
27+ -- Chris Townsend <christopher.townsend@canonical.com> Wed, 10 Dec 2014 08:19:58 -0500
28+
29 compiz (1:0.9.12.0+15.04.20141120-0ubuntu3) vivid; urgency=medium
30
31 * Drop gnome-python dependenices, as python-gconf was only used in 2012
32
33=== modified file 'debian/patches/100_workaround_virtualbox_hang.patch'
34--- debian/patches/100_workaround_virtualbox_hang.patch 2014-03-03 14:32:56 +0000
35+++ debian/patches/100_workaround_virtualbox_hang.patch 2014-12-10 19:46:40 +0000
36@@ -79,10 +79,10 @@
37 bool incorrectRefreshRate; // hack for NVIDIA specifying an incorrect
38 // refresh rate, causing us to miss vblanks
39
40-@@ -253,6 +273,10 @@
41- bool postprocessingRequired;
42- mutable CompString prevRegex;
43- mutable bool prevBlacklisted;
44+@@ -266,6 +266,10 @@
45+ std::vector<XToGLSync*>::size_type currentSyncNum;
46+ XToGLSync *currentSync;
47+ std::vector<XToGLSync*>::size_type warmupSyncs;
48 +
49 + private:
50 +
51
52=== modified file 'plugins/opengl/include/opengl/opengl.h'
53--- plugins/opengl/include/opengl/opengl.h 2013-04-27 23:30:28 +0000
54+++ plugins/opengl/include/opengl/opengl.h 2014-12-10 19:46:40 +0000
55@@ -36,7 +36,9 @@
56 #include <EGL/eglext.h>
57 #else
58 #include <GL/gl.h>
59+#include <GL/glext.h>
60 #include <GL/glx.h>
61+#include <inttypes.h>
62
63 /* Some implementations have not yet given a definition
64 * to GLX_BACK_BUFFER_AGE_EXT but this is the token as defined
65@@ -117,6 +119,39 @@
66 #define GLX_FRONT_LEFT_EXT 0x20DE
67 #endif
68
69+#ifndef GL_ARB_sync
70+# ifndef GL_ES_VERSION_2_0
71+typedef struct __GLsync *GLsync;
72+typedef int64_t GLint64;
73+typedef uint64_t GLuint64;
74+typedef intptr_t GLintptr;
75+# endif
76+
77+# ifdef GL_APPLE_sync
78+# define GL_TIMEOUT_IGNORED GL_TIMEOUT_IGNORED_APPLE
79+# define GL_ALREADY_SIGNALED GL_ALREADY_SIGNALED_APPLE
80+# define GL_TIMEOUT_EXPIRED GL_TIMEOUT_EXPIRED_APPLE
81+# define GL_CONDITION_SATISFIED GL_CONDITION_SATISFIED_APPLE
82+# define GL_WAIT_FAILED GL_WAIT_FAILED_APPLE
83+# define GL_SYNC_GPU_COMMANDS_COMPLETE GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE
84+# define GL_SYNC_STATUS GL_SYNC_STATUS _APPLE
85+# define GL_SIGNALED GL_SIGNALED_APPLE
86+# else
87+# define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
88+# define GL_ALREADY_SIGNALED 0x911A
89+# define GL_TIMEOUT_EXPIRED 0x911B
90+# define GL_CONDITION_SATISFIED 0x911C
91+# define GL_WAIT_FAILED 0x911D
92+# define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
93+# define GL_SYNC_STATUS 0x9114
94+# define GL_SIGNALED 0x9119
95+# endif
96+#endif
97+
98+#ifndef GL_EXT_x11_sync_object
99+#define GL_SYNC_X11_FENCE_EXT 0x90E1
100+#endif
101+
102 namespace GL {
103 #ifdef USE_GLES
104 typedef EGLImageKHR (*EGLCreateImageKHRProc) (EGLDisplay dpy,
105@@ -320,6 +355,24 @@
106 GLsizei width,
107 GLsizei height);
108
109+ typedef GLsync (*GLFenceSyncProc) (GLenum condition, GLbitfield flags);
110+ typedef void (*GLDeleteSyncProc) (GLsync sync);
111+ typedef GLenum (*GLClientWaitSyncProc) (GLsync sync,
112+ GLbitfield flags,
113+ GLuint64 timeout);
114+ typedef void (*GLWaitSyncProc) (GLsync sync,
115+ GLbitfield flags,
116+ GLuint64 timeout);
117+ typedef void (*GLGetSyncivProc) (GLsync sync,
118+ GLenum pname,
119+ GLsizei bufSize,
120+ GLsizei *length,
121+ GLint *values);
122+
123+ typedef GLsync (*GLImportSyncProc) (GLenum external_sync_type,
124+ GLintptr external_sync,
125+ GLbitfield flags);
126+
127
128 /* GL_ARB_shader_objects */
129 #ifndef USE_GLES
130@@ -519,6 +572,14 @@
131
132 #endif
133
134+ extern GLFenceSyncProc fenceSync;
135+ extern GLDeleteSyncProc deleteSync;
136+ extern GLClientWaitSyncProc clientWaitSync;
137+ extern GLWaitSyncProc waitSync;
138+ extern GLGetSyncivProc getSynciv;
139+
140+ extern GLImportSyncProc importSync;
141+
142 extern bool textureFromPixmap;
143 extern bool textureRectangle;
144 extern bool textureNonPowerOfTwo;
145@@ -538,6 +599,9 @@
146 extern GLint maxTextureUnits;
147 extern bool bufferAge;
148
149+ extern bool sync;
150+ extern bool xToGLSync;
151+
152 extern bool canDoSaturated;
153 extern bool canDoSlightlySaturated;
154
155
156=== added file 'plugins/opengl/include/opengl/xtoglsync.h'
157--- plugins/opengl/include/opengl/xtoglsync.h 1970-01-01 00:00:00 +0000
158+++ plugins/opengl/include/opengl/xtoglsync.h 2014-12-10 19:46:40 +0000
159@@ -0,0 +1,99 @@
160+/*
161+ * Copyright © 2011 NVIDIA Corporation
162+ *
163+ * Permission to use, copy, modify, distribute, and sell this software
164+ * and its documentation for any purpose is hereby granted without
165+ * fee, provided that the above copyright notice appear in all copies
166+ * and that both that copyright notice and this permission notice
167+ * appear in supporting documentation, and that the name of
168+ * NVIDIA Corporation not be used in advertising or publicity pertaining to
169+ * distribution of the software without specific, written prior permission.
170+ * NVIDIA Corporation makes no representations about the suitability of this
171+ * software for any purpose. It is provided "as is" without express or
172+ * implied warranty.
173+ *
174+ * NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
175+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
176+ * NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
177+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
178+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
179+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
180+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
181+ *
182+ * Authors: James Jones <jajones@nvidia.com>
183+ */
184+
185+#ifndef _GLXTOGLSYNC_H
186+#define _GLXTOGLSYNC_H
187+
188+#include <composite/composite.h>
189+#include <opengl/opengl.h>
190+#include <X11/extensions/sync.h>
191+
192+#include "opengl/opengl.h"
193+
194+/**
195+ * Class that manages an XFenceSync wrapped in a GLsync object.
196+ *
197+ * Can be used to synchronize operations in the GL command stream
198+ * with operations in the X command stream.
199+ */
200+class XToGLSync {
201+ public:
202+ XToGLSync ();
203+ ~XToGLSync ();
204+
205+ XSyncAlarm alarm (void) const { return a; }
206+ bool isReady (void) const { return state == XTOGLS_READY; }
207+
208+ /**
209+ * Sends the trigger request to the server. The fence will be signaled
210+ * after all rendering has completed.
211+ */
212+ void trigger (void);
213+
214+ /**
215+ * Calls glWaitSync. Any OpenGL commands after this will wait for the
216+ * fence to be signaled.
217+ */
218+ void insertWait (void);
219+
220+ /**
221+ * Blocks until the fence is signaled, or until a timeout expires.
222+ *
223+ * \param The maximum time to wait, in nanoseconds.
224+ * \return One of \c GL_ALREADY_SIGNALED, \c GL_CONDITION_SATISFIED,
225+ * \c GL_TIMEOUT_EXPIRED, or \c GL_WAIT_FAILED.
226+ */
227+ GLenum checkUpdateFinished (GLuint64 timeout);
228+
229+ /**
230+ * Resets the fence.
231+ */
232+ void reset (void);
233+ void handleEvent (XSyncAlarmNotifyEvent *ev);
234+
235+ private:
236+ XSyncFence f;
237+ GLsync fGL;
238+
239+ XSyncCounter c;
240+ XSyncAlarm a;
241+ XSyncValue nextCounterValue;
242+
243+ enum {
244+ XTOGLS_READY,
245+ XTOGLS_TRIGGER_SENT,
246+ XTOGLS_WAITING,
247+ XTOGLS_DONE,
248+ XTOGLS_RESET_PENDING,
249+ } state;
250+
251+ static bool syncValuesInitialized;
252+ static XSyncValue zero;
253+ static XSyncValue one;
254+
255+ static Bool alarmEventPredicate (Display *dpy, XEvent *ev, XPointer arg);
256+};
257+
258+#endif
259
260=== modified file 'plugins/opengl/opengl.xml.in'
261--- plugins/opengl/opengl.xml.in 2012-12-17 10:53:59 +0000
262+++ plugins/opengl/opengl.xml.in 2014-12-10 19:46:40 +0000
263@@ -59,6 +59,11 @@
264 <_long>Use glXSwapBuffers to display every frame. This eliminates visible tearing with most drivers and dramatically improves visual smoothness. Automatically enabled when framebuffer_object is on.</_long>
265 <default>true</default>
266 </option>
267+ <option name="enable_x11_sync" type="bool">
268+ <_short>X11 Sync objects</_short>
269+ <_long>Use X11 Sync fences to synchronize rendering between X11 and OpenGL (GL_EXT_x11_sync_object). Without this, the contents of windows may not be completely redrawn.</_long>
270+ <default>true</default>
271+ </option>
272 <option name="unredirect_driver_blacklist" type="string">
273 <_short>Unredirect Driver Blacklist</_short>
274 <_long>If non-empty, specifies a POSIX (extended) regular expression to match against the OpenGL driver strings (newline separated): "GL_VENDOR\nGL_RENDERER\nGL_VERSION". If the regular expression matches a substring of that concatenation then no windows will ever be unredirected while using that particular graphics driver.</_long>
275
276=== modified file 'plugins/opengl/src/privates.h'
277--- plugins/opengl/src/privates.h 2013-04-25 17:01:46 +0000
278+++ plugins/opengl/src/privates.h 2014-12-10 19:46:40 +0000
279@@ -35,6 +35,7 @@
280
281 #include <composite/composite.h>
282 #include <opengl/opengl.h>
283+#include <opengl/xtoglsync.h>
284 #include <core/atoms.h>
285 #include <core/configurerequestbuffer.h>
286
287@@ -184,6 +185,12 @@
288
289 void updateView ();
290
291+ bool syncObjectsInitialized () const;
292+ bool syncObjectsEnabled ();
293+ void initXToGLSyncs ();
294+ void destroyXToGLSyncs ();
295+ void updateXToGLSyncs ();
296+
297 bool driverIsBlacklisted (const char *regex) const;
298
299 bool postprocessRequiredForCurrentFrame ();
300@@ -253,6 +260,12 @@
301 bool postprocessingRequired;
302 mutable CompString prevRegex;
303 mutable bool prevBlacklisted;
304+
305+ std::vector<XToGLSync*> xToGLSyncs;
306+ std::map<XSyncAlarm, XToGLSync*> alarmToSync;
307+ std::vector<XToGLSync*>::size_type currentSyncNum;
308+ XToGLSync *currentSync;
309+ std::vector<XToGLSync*>::size_type warmupSyncs;
310 };
311
312 class PrivateGLWindow :
313
314=== modified file 'plugins/opengl/src/screen.cpp'
315--- plugins/opengl/src/screen.cpp 2013-10-30 20:31:20 +0000
316+++ plugins/opengl/src/screen.cpp 2014-12-10 19:46:40 +0000
317@@ -68,6 +68,16 @@
318
319 using namespace compiz::opengl;
320
321+/**
322+ * The number of X11 sync objects to create.
323+ */
324+static const size_t NUM_X11_SYNCS = 16;
325+
326+/**
327+ * The maximum time to wait for a sync object, in nanoseconds.
328+ */
329+static const GLuint64 MAX_SYNC_WAIT_TIME = 1000000000ull; // One second
330+
331 namespace GL {
332 #ifdef USE_GLES
333 EGLCreateImageKHRProc createImage;
334@@ -170,6 +180,14 @@
335 GLBindRenderbufferProc bindRenderbuffer = NULL;
336 GLRenderbufferStorageProc renderbufferStorage = NULL;
337
338+ GLFenceSyncProc fenceSync = NULL;
339+ GLDeleteSyncProc deleteSync = NULL;
340+ GLClientWaitSyncProc clientWaitSync = NULL;
341+ GLWaitSyncProc waitSync = NULL;
342+ GLGetSyncivProc getSynciv = NULL;
343+
344+ GLImportSyncProc importSync = NULL;
345+
346 bool textureFromPixmap = true;
347 bool textureRectangle = false;
348 bool textureNonPowerOfTwo = false;
349@@ -188,6 +206,9 @@
350 GLint maxTextureUnits = 1;
351 bool bufferAge = false;
352
353+ bool sync = false;
354+ bool xToGLSync = false;
355+
356 bool canDoSaturated = false;
357 bool canDoSlightlySaturated = false;
358
359@@ -1054,6 +1075,36 @@
360 if (strstr (glExtensions, "GL_ARB_texture_compression"))
361 GL::textureCompression = true;
362
363+ if (strstr (glExtensions, "GL_ARB_sync"))
364+ {
365+ GL::fenceSync = (GL::GLFenceSyncProc)
366+ getProcAddress ("glFenceSync");
367+ GL::deleteSync = (GL::GLDeleteSyncProc)
368+ getProcAddress ("glDeleteSync");
369+ GL::clientWaitSync = (GL::GLClientWaitSyncProc)
370+ getProcAddress ("glClientWaitSync");
371+ GL::waitSync = (GL::GLWaitSyncProc)
372+ getProcAddress ("glWaitSync");
373+ GL::getSynciv = (GL::GLGetSyncivProc)
374+ getProcAddress ("glGetSynciv");
375+
376+ if (GL::fenceSync &&
377+ GL::deleteSync &&
378+ GL::clientWaitSync &&
379+ GL::waitSync &&
380+ GL::getSynciv)
381+ GL::sync = true;
382+ }
383+
384+ if (strstr (glExtensions, "GL_EXT_x11_sync_object"))
385+ {
386+ GL::importSync = (GL::GLImportSyncProc)
387+ getProcAddress ("glImportSyncEXT");
388+
389+ if (GL::importSync)
390+ GL::xToGLSync = true;
391+ }
392+
393 glClearColor (0.0, 0.0, 0.0, 1.0);
394 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
395 glEnable (GL_CULL_FACE);
396@@ -1257,6 +1308,8 @@
397 getProcAddress ("glXSwapIntervalSGI");
398 }
399
400+ priv->initXToGLSyncs ();
401+
402 fbConfigs = (*GL::getFBConfigs) (dpy, s->screenNum (), &nElements);
403
404 GL::stencilBuffer = false;
405@@ -1411,6 +1464,9 @@
406
407 GLScreen::~GLScreen ()
408 {
409+ // Must occur before context is destroyed.
410+ priv->destroyXToGLSyncs ();
411+
412 if (priv->hasCompositing)
413 CompositeScreen::get (screen)->unregisterPaintHandler ();
414
415@@ -1471,7 +1527,10 @@
416 glVersion (NULL),
417 postprocessingRequired (false),
418 prevRegex (),
419- prevBlacklisted (false)
420+ prevBlacklisted (false),
421+ currentSyncNum (0),
422+ currentSync (0),
423+ warmupSyncs (0)
424 {
425 ScreenInterface::setHandler (screen);
426 CompositeScreenInterface::setHandler (cScreen);
427@@ -1563,6 +1622,16 @@
428 * be recopying the root window pixmap all the time
429 * which is no good, so don't do that */
430 }
431+ else if (event->type == screen->syncEvent () + XSyncAlarmNotify)
432+ {
433+ XSyncAlarmNotifyEvent *ae =
434+ reinterpret_cast<XSyncAlarmNotifyEvent*>(event);
435+ std::map<XSyncAlarm, XToGLSync*>::iterator it =
436+ alarmToSync.find (ae->alarm);
437+
438+ if (it != alarmToSync.end ())
439+ it->second->handleEvent (ae);
440+ }
441 break;
442 }
443 }
444@@ -2026,6 +2095,101 @@
445 {
446 }
447
448+bool
449+PrivateGLScreen::syncObjectsInitialized () const
450+{
451+ return !xToGLSyncs.empty ();
452+}
453+
454+bool
455+PrivateGLScreen::syncObjectsEnabled ()
456+{
457+ return GL::sync && GL::xToGLSync && optionGetEnableX11Sync ();
458+}
459+
460+void
461+PrivateGLScreen::initXToGLSyncs ()
462+{
463+ assert (!syncObjectsInitialized ());
464+ assert (xToGLSyncs.empty ());
465+ assert (alarmToSync.empty ());
466+
467+ if (syncObjectsEnabled () && !syncObjectsInitialized ())
468+ {
469+ xToGLSyncs.resize (NUM_X11_SYNCS, NULL);
470+
471+ foreach (XToGLSync*& sync, xToGLSyncs)
472+ {
473+ sync = new XToGLSync ();
474+ alarmToSync[sync->alarm ()] = sync;
475+ }
476+
477+ currentSyncNum = 0;
478+ currentSync = xToGLSyncs[0];
479+ warmupSyncs = 0;
480+ }
481+}
482+
483+void
484+PrivateGLScreen::destroyXToGLSyncs ()
485+{
486+ if (syncObjectsInitialized ())
487+ {
488+ foreach (XToGLSync* sync, xToGLSyncs)
489+ delete sync;
490+ xToGLSyncs.resize (0);
491+ }
492+ alarmToSync.clear ();
493+ currentSyncNum = 0;
494+ currentSync = NULL;
495+ warmupSyncs = 0;
496+}
497+
498+void
499+PrivateGLScreen::updateXToGLSyncs ()
500+{
501+ const std::vector<XToGLSync*>::size_type numSyncs = xToGLSyncs.size ();
502+
503+ if (numSyncs)
504+ {
505+ if (warmupSyncs >= numSyncs / 2)
506+ {
507+ const std::vector<XToGLSync*>::size_type resetSyncIdx =
508+ (currentSyncNum + (numSyncs / 2)) % numSyncs;
509+
510+ XToGLSync* syncToReset = xToGLSyncs[resetSyncIdx];
511+
512+ GLenum status = syncToReset->checkUpdateFinished (0);
513+ if (status == GL_TIMEOUT_EXPIRED)
514+ {
515+ status = syncToReset->checkUpdateFinished (MAX_SYNC_WAIT_TIME);
516+ }
517+
518+ if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED)
519+ {
520+ // This should never happen. If there was an error somewhere,
521+ // then we don't want to risk a hang here, so just destroy the
522+ // sync objects. We'll recreate them again in the next call to
523+ // prepareDrawing.
524+ compLogMessage ("opengl", CompLogLevelError, "Timed out waiting for sync object.");
525+ destroyXToGLSyncs ();
526+ return;
527+ }
528+
529+ syncToReset->reset ();
530+ }
531+ else
532+ {
533+ warmupSyncs++;
534+ }
535+
536+ currentSyncNum++;
537+ currentSyncNum %= numSyncs;
538+
539+ currentSync = xToGLSyncs[currentSyncNum];
540+ }
541+}
542+
543 #ifndef USE_GLES
544
545 void
546@@ -2199,6 +2363,9 @@
547 glClear (GL_COLOR_BUFFER_BIT);
548 }
549
550+ if (currentSync)
551+ currentSync->insertWait ();
552+
553 // Disable everything that we don't usually need and could slow us down
554 glDisable (GL_BLEND);
555 glDisable (GL_STENCIL_TEST);
556@@ -2352,6 +2519,8 @@
557 doubleBuffer.render (paintRegion, fullscreen);
558
559 lastMask = mask;
560+
561+ updateXToGLSyncs ();
562 }
563
564 unsigned int
565@@ -2448,6 +2617,55 @@
566 updateFrameProvider ();
567 CompositeScreen::get (screen)->damageScreen ();
568 }
569+
570+ // Check if the option to use sync objects has been enabled or disabled.
571+ if (syncObjectsEnabled () && !syncObjectsInitialized ())
572+ {
573+ initXToGLSyncs ();
574+ }
575+ else if (!syncObjectsEnabled () && syncObjectsInitialized ())
576+ {
577+ destroyXToGLSyncs ();
578+ }
579+
580+ if (currentSync)
581+ {
582+ if (!currentSync->isReady ())
583+ {
584+ for (std::vector<XToGLSync*>::size_type i = xToGLSyncs.size () / 2; i > 0; i--)
585+ {
586+ // try to check next sync
587+ updateXToGLSyncs ();
588+
589+ // method updateXToGLSync may disable syncs
590+ if (!currentSync)
591+ break;
592+
593+ if (currentSync->isReady ())
594+ break;
595+ }
596+ }
597+ }
598+
599+ if (currentSync)
600+ {
601+ if (!currentSync->isReady ())
602+ {
603+ // If this happens, then we must have missed an event or update
604+ // somewhere. Destroy and recreate the sync objects to put us back
605+ // into a good state.
606+ destroyXToGLSyncs ();
607+ initXToGLSyncs ();
608+ }
609+ }
610+
611+ if (currentSync)
612+ {
613+ // Tell the server to trigger the fence object after all rendering has
614+ // completed.
615+ assert (currentSync->isReady ());
616+ currentSync->trigger ();
617+ }
618 }
619
620 bool
621
622=== added file 'plugins/opengl/src/xtoglsync.cpp'
623--- plugins/opengl/src/xtoglsync.cpp 1970-01-01 00:00:00 +0000
624+++ plugins/opengl/src/xtoglsync.cpp 2014-12-10 19:46:40 +0000
625@@ -0,0 +1,194 @@
626+/*
627+ * Copyright © 2011 NVIDIA Corporation
628+ *
629+ * Permission to use, copy, modify, distribute, and sell this software
630+ * and its documentation for any purpose is hereby granted without
631+ * fee, provided that the above copyright notice appear in all copies
632+ * and that both that copyright notice and this permission notice
633+ * appear in supporting documentation, and that the name of
634+ * NVIDIA Corporation not be used in advertising or publicity pertaining to
635+ * distribution of the software without specific, written prior permission.
636+ * NVIDIA Corporation makes no representations about the suitability of this
637+ * software for any purpose. It is provided "as is" without express or
638+ * implied warranty.
639+ *
640+ * NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
641+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
642+ * NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
643+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
644+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
645+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
646+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
647+ *
648+ * Authors: James Jones <jajones@nvidia.com>
649+ */
650+
651+#include "opengl/xtoglsync.h"
652+
653+bool XToGLSync::syncValuesInitialized = false;
654+XSyncValue XToGLSync::zero;
655+XSyncValue XToGLSync::one;
656+
657+XToGLSync::XToGLSync () :
658+ f (None),
659+ fGL (NULL),
660+ c (None),
661+ a (None),
662+ state (XToGLSync::XTOGLS_READY)
663+{
664+ Display *dpy = screen->dpy ();
665+
666+ f = XSyncCreateFence (dpy, DefaultRootWindow (dpy), False);
667+ fGL = GL::importSync (GL_SYNC_X11_FENCE_EXT, f, 0);
668+
669+ if (!syncValuesInitialized)
670+ {
671+ XSyncIntToValue (&zero, 0);
672+ XSyncIntToValue (&one, 1);
673+ syncValuesInitialized = true;
674+ }
675+
676+ XSyncIntToValue (&nextCounterValue, 1);
677+ c = XSyncCreateCounter (dpy, zero);
678+
679+ XSyncAlarmAttributes alarmAttribs;
680+ alarmAttribs.trigger.counter = c;
681+ alarmAttribs.trigger.value_type = XSyncAbsolute;
682+ alarmAttribs.trigger.wait_value = one;
683+ alarmAttribs.trigger.test_type = XSyncPositiveTransition;
684+ alarmAttribs.events = True;
685+ a = XSyncCreateAlarm (dpy,
686+ XSyncCACounter |
687+ XSyncCAValueType |
688+ XSyncCAValue |
689+ XSyncCATestType |
690+ XSyncCAEvents,
691+ &alarmAttribs);
692+
693+}
694+
695+XToGLSync::~XToGLSync ()
696+{
697+ Display *dpy = screen->dpy ();
698+
699+ switch (state) {
700+ case XTOGLS_WAITING:
701+ break;
702+
703+ case XTOGLS_RESET_PENDING:
704+ {
705+ XEvent ev;
706+
707+ XIfEvent (dpy, &ev, &XToGLSync::alarmEventPredicate,
708+ reinterpret_cast<XPointer>(this));
709+ handleEvent(reinterpret_cast<XSyncAlarmNotifyEvent*>(&ev));
710+ }
711+ // Fall through.
712+ case XTOGLS_READY:
713+ XSyncTriggerFence (dpy, f);
714+ XFlush (dpy);
715+ break;
716+
717+ case XTOGLS_TRIGGER_SENT:
718+ case XTOGLS_DONE:
719+ // Nothing to do.
720+ break;
721+ }
722+
723+ GL::deleteSync (fGL);
724+ XSyncDestroyFence (dpy, f);
725+ XSyncDestroyCounter (dpy, c);
726+ XSyncDestroyAlarm (dpy, a);
727+}
728+
729+Bool XToGLSync::alarmEventPredicate (Display *dpy, XEvent *ev, XPointer arg)
730+{
731+ if (ev->type == screen->syncEvent () + XSyncAlarmNotify)
732+ {
733+ XToGLSync *sync = reinterpret_cast<XToGLSync*>(arg);
734+ XSyncAlarmNotifyEvent *ae =
735+ reinterpret_cast<XSyncAlarmNotifyEvent*>(ev);
736+
737+ if (ae->alarm == sync->a)
738+ return True;
739+ }
740+
741+ return False;
742+}
743+
744+void XToGLSync::trigger (void)
745+{
746+ Display *dpy = screen->dpy ();
747+ assert (state == XTOGLS_READY);
748+
749+ XSyncTriggerFence (dpy, f);
750+ XFlush (dpy);
751+
752+ state = XTOGLS_TRIGGER_SENT;
753+}
754+
755+void XToGLSync::insertWait (void)
756+{
757+ if (state != XTOGLS_TRIGGER_SENT)
758+ return;
759+
760+ GL::waitSync (fGL, 0, GL_TIMEOUT_IGNORED);
761+
762+ state = XTOGLS_WAITING;
763+}
764+
765+GLenum XToGLSync::checkUpdateFinished (GLuint64 timeout)
766+{
767+ GLenum status;
768+
769+ switch (state) {
770+ case XTOGLS_DONE:
771+ return GL_ALREADY_SIGNALED;
772+
773+ case XTOGLS_WAITING:
774+ status = GL::clientWaitSync (fGL, 0, timeout);
775+ if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED)
776+ {
777+ state = XTOGLS_DONE;
778+ }
779+ return status;
780+
781+ default:
782+ return GL_WAIT_FAILED;
783+ }
784+}
785+
786+void XToGLSync::reset (void)
787+{
788+ Display *dpy = screen->dpy ();
789+ if (state != XTOGLS_DONE)
790+ {
791+ return;
792+ }
793+
794+ XSyncResetFence (dpy, f);
795+
796+ XSyncAlarmAttributes values;
797+ values.trigger.wait_value = nextCounterValue;
798+ XSyncChangeAlarm (dpy, a, XSyncCAValue, &values);
799+ XSyncSetCounter (dpy, c, nextCounterValue);
800+
801+ int overflow;
802+ XSyncValueAdd (&nextCounterValue, nextCounterValue, one, &overflow);
803+
804+ state = XTOGLS_RESET_PENDING;
805+}
806+
807+void XToGLSync::handleEvent (XSyncAlarmNotifyEvent* ae)
808+{
809+ if (ae->alarm == a)
810+ {
811+ if (state != XTOGLS_RESET_PENDING)
812+ {
813+ return;
814+ }
815+
816+ state = XTOGLS_READY;
817+ }
818+}
819+

Subscribers

People subscribed via source and target branches