~saviq/qtubuntu/revert-occlude-lp1620297

« back to all changes in this revision

Viewing changes to src/ubuntumirclient/glcontext.cpp

  • Committer: Bileto Bot
  • Author(s): Gerry Boland
  • Date: 2016-08-09 23:00:16 UTC
  • mfrom: (328.3.4 eglconvenience-retry)
  • Revision ID: ci-train-bot@canonical.com-20160809230016-nutnvedrejhvzrdc
Reapply rev 324 plus fix: EGL convenience, plus workaround for hybris not supporting GLESv3. (LP: #1507817, #1594198)

Approved by: Daniel d'Andrada, Unity8 CI Bot

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
namespace {
27
27
 
28
 
void printOpenGLESConfig() {
29
 
    static bool once = true;
30
 
    if (once) {
31
 
        const char* string = (const char*) glGetString(GL_VENDOR);
32
 
        qCDebug(ubuntumirclient, "OpenGL ES vendor: %s", string);
33
 
        string = (const char*) glGetString(GL_RENDERER);
34
 
        qCDebug(ubuntumirclient, "OpenGL ES renderer: %s", string);
35
 
        string = (const char*) glGetString(GL_VERSION);
36
 
        qCDebug(ubuntumirclient, "OpenGL ES version: %s", string);
37
 
        string = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
38
 
        qCDebug(ubuntumirclient, "OpenGL ES Shading Language version: %s", string);
39
 
        string = (const char*) glGetString(GL_EXTENSIONS);
40
 
        qCDebug(ubuntumirclient, "OpenGL ES extensions: %s", string);
41
 
        once = false;
42
 
    }
43
 
}
44
 
 
45
 
void printEglConfig(EGLDisplay display, EGLConfig config) {
 
28
void printEglConfig(EGLDisplay display, EGLConfig config)
 
29
{
46
30
    Q_ASSERT(display != EGL_NO_DISPLAY);
47
31
    Q_ASSERT(config != nullptr);
48
32
 
49
 
    static const struct { const EGLint attrib; const char* name; } kAttribs[] = {
50
 
        { EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE" },
51
 
        { EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE" },
52
 
        { EGL_BLUE_SIZE, "EGL_BLUE_SIZE" },
53
 
        { EGL_GREEN_SIZE, "EGL_GREEN_SIZE" },
54
 
        { EGL_RED_SIZE, "EGL_RED_SIZE" },
55
 
        { EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE" },
56
 
        { EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE" },
57
 
        { EGL_CONFIG_CAVEAT, "EGL_CONFIG_CAVEAT" },
58
 
        { EGL_CONFIG_ID, "EGL_CONFIG_ID" },
59
 
        { EGL_LEVEL, "EGL_LEVEL" },
60
 
        { EGL_MAX_PBUFFER_HEIGHT, "EGL_MAX_PBUFFER_HEIGHT" },
61
 
        { EGL_MAX_PBUFFER_PIXELS, "EGL_MAX_PBUFFER_PIXELS" },
62
 
        { EGL_MAX_PBUFFER_WIDTH, "EGL_MAX_PBUFFER_WIDTH" },
63
 
        { EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE" },
64
 
        { EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID" },
65
 
        { EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE" },
66
 
        { EGL_SAMPLES, "EGL_SAMPLES" },
67
 
        { EGL_SAMPLE_BUFFERS, "EGL_SAMPLE_BUFFERS" },
68
 
        { EGL_SURFACE_TYPE, "EGL_SURFACE_TYPE" },
69
 
        { EGL_TRANSPARENT_TYPE, "EGL_TRANSPARENT_TYPE" },
70
 
        { EGL_TRANSPARENT_BLUE_VALUE, "EGL_TRANSPARENT_BLUE_VALUE" },
71
 
        { EGL_TRANSPARENT_GREEN_VALUE, "EGL_TRANSPARENT_GREEN_VALUE" },
72
 
        { EGL_TRANSPARENT_RED_VALUE, "EGL_TRANSPARENT_RED_VALUE" },
73
 
        { EGL_BIND_TO_TEXTURE_RGB, "EGL_BIND_TO_TEXTURE_RGB" },
74
 
        { EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA" },
75
 
        { EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL" },
76
 
        { EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL" },
77
 
        { -1, NULL }
78
 
    };
79
 
    const char* string = eglQueryString(display, EGL_VENDOR);
 
33
    const char *string = eglQueryString(display, EGL_VENDOR);
80
34
    qCDebug(ubuntumirclient, "EGL vendor: %s", string);
81
35
 
82
36
    string = eglQueryString(display, EGL_VERSION);
85
39
    string = eglQueryString(display, EGL_EXTENSIONS);
86
40
    qCDebug(ubuntumirclient, "EGL extensions: %s", string);
87
41
 
88
 
    qCDebug(ubuntumirclient, "EGL configuration attibutes:");
89
 
    for (int index = 0; kAttribs[index].attrib != -1; index++) {
90
 
        EGLint value;
91
 
        if (eglGetConfigAttrib(display, config, kAttribs[index].attrib, &value))
92
 
            qCDebug(ubuntumirclient, "  %s: %d", kAttribs[index].name, static_cast<int>(value));
93
 
    }
94
 
}
95
 
 
96
 
QString eglErrorToString(EGLint errorNumber)
97
 
{
98
 
    #define EGL_ERROR_CASE(error) case error: return QString(#error);
99
 
 
100
 
    switch (errorNumber) {
101
 
        EGL_ERROR_CASE(EGL_SUCCESS)
102
 
        EGL_ERROR_CASE(EGL_NOT_INITIALIZED)
103
 
        EGL_ERROR_CASE(EGL_BAD_ACCESS)
104
 
        EGL_ERROR_CASE(EGL_BAD_ALLOC)
105
 
        EGL_ERROR_CASE(EGL_BAD_ATTRIBUTE)
106
 
        EGL_ERROR_CASE(EGL_BAD_CONTEXT)
107
 
        EGL_ERROR_CASE(EGL_BAD_CONFIG)
108
 
        EGL_ERROR_CASE(EGL_BAD_CURRENT_SURFACE)
109
 
        EGL_ERROR_CASE(EGL_BAD_DISPLAY)
110
 
        EGL_ERROR_CASE(EGL_BAD_SURFACE)
111
 
        EGL_ERROR_CASE(EGL_BAD_MATCH)
112
 
        EGL_ERROR_CASE(EGL_BAD_PARAMETER)
113
 
        EGL_ERROR_CASE(EGL_BAD_NATIVE_PIXMAP)
114
 
        EGL_ERROR_CASE(EGL_BAD_NATIVE_WINDOW)
115
 
        EGL_ERROR_CASE(EGL_CONTEXT_LOST)
116
 
        default:
117
 
            return QString("?");
118
 
    }
119
 
 
120
 
    #undef EGL_ERROR_CASE
121
 
}
122
 
 
123
 
EGLenum api_in_use()
124
 
{
125
 
    #ifdef QTUBUNTU_USE_OPENGL
126
 
    return EGL_OPENGL_API;
127
 
    #else
128
 
    return EGL_OPENGL_ES_API;
129
 
    #endif
130
 
}
131
 
 
132
 
const int kSwapInterval = 1;
133
 
 
134
 
int qGetEnvIntValue(const char *varName, bool *ok)
135
 
{
136
 
    return qgetenv(varName).toInt(ok);
 
42
    qCDebug(ubuntumirclient, "EGL configuration attributes:");
 
43
    q_printEglConfig(display, config);
137
44
}
138
45
 
139
46
} // anonymous namespace
140
47
 
141
 
UbuntuOpenGLContext::UbuntuOpenGLContext(const QSurfaceFormat &surfaceFormat, UbuntuOpenGLContext *share,
142
 
                                         EGLDisplay display, EGLConfig config)
143
 
    : mSurfaceFormat(surfaceFormat)
144
 
    , mEglDisplay(display)
 
48
UbuntuOpenGLContext::UbuntuOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
 
49
                                         EGLDisplay display)
 
50
    : QEGLPlatformContext(format, share, display, 0)
145
51
{
146
 
    // Create an OpenGL ES 2 context.
147
 
    QVector<EGLint> attribs;
148
 
    attribs.append(EGL_CONTEXT_CLIENT_VERSION);
149
 
    attribs.append(2);
150
 
    attribs.append(EGL_NONE);
151
 
    ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
152
 
 
153
52
    if (ubuntumirclient().isDebugEnabled()) {
154
 
        printEglConfig(mEglDisplay, config);
 
53
        printEglConfig(display, eglConfig());
155
54
    }
156
 
 
157
 
    // Set vblank swap interval.
158
 
    bool ok;
159
 
    int swapInterval = qGetEnvIntValue("QTUBUNTU_SWAPINTERVAL", &ok);
160
 
    if (!ok)
161
 
        swapInterval = kSwapInterval;
162
 
 
163
 
    qCDebug(ubuntumirclient, "Setting swap interval to %d", swapInterval);
164
 
    eglSwapInterval(mEglDisplay, swapInterval);
165
 
 
166
 
    mEglContext = eglCreateContext(mEglDisplay, config, share ? share->eglContext() : EGL_NO_CONTEXT,
167
 
                                   attribs.constData());
168
 
 
169
 
    Q_ASSERT(mEglContext != EGL_NO_CONTEXT);
170
 
}
171
 
 
172
 
UbuntuOpenGLContext::~UbuntuOpenGLContext()
173
 
{
174
 
    ASSERT(eglDestroyContext(mEglDisplay, mEglContext) == EGL_TRUE);
175
55
}
176
56
 
177
57
static bool needsFBOReadBackWorkaround()
179
59
    static bool set = false;
180
60
    static bool needsWorkaround = false;
181
61
 
182
 
    if (!set) {
 
62
    if (Q_UNLIKELY(!set)) {
183
63
        const char *rendererString = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
184
64
        needsWorkaround = qstrncmp(rendererString, "Mali-400", 8) == 0
185
65
                          || qstrncmp(rendererString, "Mali-T7", 7) == 0
202
82
        }
203
83
        return offscreen->buffer()->bind();
204
84
    } else {
205
 
        EGLSurface eglSurface = static_cast<UbuntuWindow*>(surface)->eglSurface();
206
 
        ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
207
 
 
208
 
        EGLBoolean result = eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext);
209
 
        if (result == EGL_FALSE) {
210
 
            qCCritical(ubuntumirclient, "eglMakeCurrent() failed with %s",
211
 
                    qPrintable(eglErrorToString(eglGetError())));
212
 
            return false;
213
 
        }
214
 
 
215
 
        QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context());
216
 
        if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) {
217
 
            ctx_d->workaround_brokenFBOReadBack = true;
218
 
        }
219
 
 
220
 
        if (ubuntumirclient().isDebugEnabled()) {
221
 
            printOpenGLESConfig();
222
 
        }
223
 
        return true;
 
85
        const bool ret = QEGLPlatformContext::makeCurrent(surface);
 
86
 
 
87
        if (Q_LIKELY(ret)) {
 
88
            QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context());
 
89
            if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) {
 
90
                ctx_d->workaround_brokenFBOReadBack = true;
 
91
            }
 
92
        }
 
93
 
 
94
        return ret;
224
95
    }
225
96
}
226
97
 
227
 
void UbuntuOpenGLContext::doneCurrent()
 
98
// Following method used internally in the base class QEGLPlatformContext to access
 
99
// the egl surface of a QPlatformSurface/UbuntuWindow
 
100
EGLSurface UbuntuOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
228
101
{
229
 
    ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
230
 
    ASSERT(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) == EGL_TRUE);
 
102
    auto ubuntuWindow = static_cast<UbuntuWindow *>(surface);
 
103
    return ubuntuWindow->eglSurface();
231
104
}
232
105
 
233
 
void UbuntuOpenGLContext::swapBuffers(QPlatformSurface* surface)
 
106
void UbuntuOpenGLContext::swapBuffers(QPlatformSurface *surface)
234
107
{
235
 
    UbuntuWindow *ubuntuWindow = static_cast<UbuntuWindow*>(surface);
236
 
 
237
 
    EGLSurface eglSurface = ubuntuWindow->eglSurface();
238
 
    ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
239
 
    ASSERT(eglSwapBuffers(mEglDisplay, eglSurface) == EGL_TRUE);
240
 
 
 
108
    QEGLPlatformContext::swapBuffers(surface);
 
109
 
 
110
    // notify window on swap completion
 
111
    auto ubuntuWindow = static_cast<UbuntuWindow *>(surface);
241
112
    ubuntuWindow->onSwapBuffersDone();
242
113
}
243
 
 
244
 
void (*UbuntuOpenGLContext::getProcAddress(const QByteArray& procName)) ()
245
 
{
246
 
    ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
247
 
    return eglGetProcAddress(procName.constData());
248
 
}