~compiz-team/compiz/0.9.11

« back to all changes in this revision

Viewing changes to plugins/opengl/src/xtoglsync.cpp

  • Committer: CI Train Bot
  • Author(s): Stephen M. Webb
  • Date: 2015-01-22 14:51:41 UTC
  • mfrom: (3869.1.2 lp-269904-trusty)
  • Revision ID: ci-train-bot@canonical.com-20150122145141-m6fpm6djd2s54try
Use the GL_EXT_x11_sync_object OpenGL extension to synchronize updates with X11 to avoid unrefreshed parts of the screen on Nvidia hardware. Fixes: #269904
Approved by: Christopher Townsend

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2011 NVIDIA Corporation
 
3
 *
 
4
 * Permission to use, copy, modify, distribute, and sell this software
 
5
 * and its documentation for any purpose is hereby granted without
 
6
 * fee, provided that the above copyright notice appear in all copies
 
7
 * and that both that copyright notice and this permission notice
 
8
 * appear in supporting documentation, and that the name of
 
9
 * NVIDIA Corporation not be used in advertising or publicity pertaining to
 
10
 * distribution of the software without specific, written prior permission.
 
11
 * NVIDIA Corporation makes no representations about the suitability of this
 
12
 * software for any purpose. It is provided "as is" without express or
 
13
 * implied warranty.
 
14
 *
 
15
 * NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
16
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
 
17
 * NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
18
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 
19
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 
20
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 
21
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
22
 *
 
23
 * Authors: James Jones <jajones@nvidia.com>
 
24
 */
 
25
 
 
26
#include "opengl/xtoglsync.h"
 
27
 
 
28
bool XToGLSync::syncValuesInitialized = false;
 
29
XSyncValue XToGLSync::zero;
 
30
XSyncValue XToGLSync::one;
 
31
 
 
32
XToGLSync::XToGLSync () :
 
33
    f (None),
 
34
    fGL (NULL),
 
35
    c (None),
 
36
    a (None),
 
37
    state (XToGLSync::XTOGLS_READY)
 
38
{
 
39
    Display *dpy = screen->dpy ();
 
40
 
 
41
    f = XSyncCreateFence (dpy, DefaultRootWindow (dpy), False);
 
42
    fGL = GL::importSync (GL_SYNC_X11_FENCE_EXT, f, 0);
 
43
 
 
44
    if (!syncValuesInitialized)
 
45
    {
 
46
        XSyncIntToValue (&zero, 0);
 
47
        XSyncIntToValue (&one, 1);
 
48
        syncValuesInitialized = true;
 
49
    }
 
50
 
 
51
    XSyncIntToValue (&nextCounterValue, 1);
 
52
    c = XSyncCreateCounter (dpy, zero);
 
53
 
 
54
    XSyncAlarmAttributes alarmAttribs;
 
55
    alarmAttribs.trigger.counter = c;
 
56
    alarmAttribs.trigger.value_type = XSyncAbsolute;
 
57
    alarmAttribs.trigger.wait_value = one;
 
58
    alarmAttribs.trigger.test_type = XSyncPositiveTransition;
 
59
    alarmAttribs.events = True;
 
60
    a = XSyncCreateAlarm (dpy,
 
61
                          XSyncCACounter |
 
62
                          XSyncCAValueType |
 
63
                          XSyncCAValue |
 
64
                          XSyncCATestType |
 
65
                          XSyncCAEvents,
 
66
                          &alarmAttribs);
 
67
 
 
68
}
 
69
 
 
70
XToGLSync::~XToGLSync ()
 
71
{
 
72
    Display *dpy = screen->dpy ();
 
73
 
 
74
    switch (state) {
 
75
    case XTOGLS_WAITING:
 
76
        break;
 
77
 
 
78
    case XTOGLS_RESET_PENDING:
 
79
        {
 
80
            XEvent ev;
 
81
 
 
82
            XIfEvent (dpy, &ev, &XToGLSync::alarmEventPredicate,
 
83
                      reinterpret_cast<XPointer>(this));
 
84
            handleEvent(reinterpret_cast<XSyncAlarmNotifyEvent*>(&ev));
 
85
        }
 
86
        // Fall through.
 
87
    case XTOGLS_READY:
 
88
        XSyncTriggerFence (dpy, f);
 
89
        XFlush (dpy);
 
90
        break;
 
91
 
 
92
    case XTOGLS_TRIGGER_SENT:
 
93
    case XTOGLS_DONE:
 
94
        // Nothing to do.
 
95
        break;
 
96
    }
 
97
 
 
98
    GL::deleteSync (fGL);
 
99
    XSyncDestroyFence (dpy, f);
 
100
    XSyncDestroyCounter (dpy, c);
 
101
    XSyncDestroyAlarm (dpy, a);
 
102
}
 
103
 
 
104
Bool XToGLSync::alarmEventPredicate (Display *dpy, XEvent *ev, XPointer arg)
 
105
{
 
106
    if (ev->type == screen->syncEvent () + XSyncAlarmNotify)
 
107
    {
 
108
        XToGLSync *sync = reinterpret_cast<XToGLSync*>(arg);
 
109
        XSyncAlarmNotifyEvent *ae =
 
110
            reinterpret_cast<XSyncAlarmNotifyEvent*>(ev);
 
111
 
 
112
        if (ae->alarm == sync->a)
 
113
            return True;
 
114
    }
 
115
 
 
116
    return False;
 
117
}
 
118
 
 
119
void XToGLSync::trigger (void)
 
120
{
 
121
    Display *dpy = screen->dpy ();
 
122
    assert (state == XTOGLS_READY);
 
123
 
 
124
    XSyncTriggerFence (dpy, f);
 
125
    XFlush (dpy);
 
126
 
 
127
    state = XTOGLS_TRIGGER_SENT;
 
128
}
 
129
 
 
130
void XToGLSync::insertWait (void)
 
131
{
 
132
    if (state != XTOGLS_TRIGGER_SENT)
 
133
        return;
 
134
 
 
135
    GL::waitSync (fGL, 0, GL_TIMEOUT_IGNORED);
 
136
 
 
137
    state = XTOGLS_WAITING;
 
138
}
 
139
 
 
140
GLenum XToGLSync::checkUpdateFinished (GLuint64 timeout)
 
141
{
 
142
    GLenum status;
 
143
 
 
144
    switch (state) {
 
145
        case XTOGLS_DONE:
 
146
            return GL_ALREADY_SIGNALED;
 
147
 
 
148
        case XTOGLS_WAITING:
 
149
            status = GL::clientWaitSync (fGL, 0, timeout);
 
150
            if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED)
 
151
            {
 
152
                state = XTOGLS_DONE;
 
153
            }
 
154
            return status;
 
155
 
 
156
        default:
 
157
            return GL_WAIT_FAILED;
 
158
    }
 
159
}
 
160
 
 
161
void XToGLSync::reset (void)
 
162
{
 
163
    Display *dpy = screen->dpy ();
 
164
    if (state != XTOGLS_DONE)
 
165
    {
 
166
        return;
 
167
    }
 
168
 
 
169
    XSyncResetFence (dpy, f);
 
170
 
 
171
    XSyncAlarmAttributes values;
 
172
    values.trigger.wait_value = nextCounterValue;
 
173
    XSyncChangeAlarm (dpy, a, XSyncCAValue, &values);
 
174
    XSyncSetCounter (dpy, c, nextCounterValue);
 
175
 
 
176
    int overflow;
 
177
    XSyncValueAdd (&nextCounterValue, nextCounterValue, one, &overflow);
 
178
 
 
179
    state = XTOGLS_RESET_PENDING;
 
180
}
 
181
 
 
182
void XToGLSync::handleEvent (XSyncAlarmNotifyEvent* ae)
 
183
{
 
184
    if (ae->alarm == a)
 
185
    {
 
186
        if (state != XTOGLS_RESET_PENDING)
 
187
        {
 
188
            return;
 
189
        }
 
190
 
 
191
        state = XTOGLS_READY;
 
192
    }
 
193
}
 
194