1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWebEngine module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "gl_context_qt.h"
41 
42 #include <QGuiApplication>
43 #include <QOpenGLContext>
44 #include <QThread>
45 #include <qpa/qplatformnativeinterface.h>
46 #include "ui/gl/gl_context_egl.h"
47 #include "ui/gl/gl_implementation.h"
48 
49 #if defined(OS_WIN)
50 #include "ui/gl/gl_context_wgl.h"
51 #endif
52 
53 QT_BEGIN_NAMESPACE
54 
55 Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context();
56 GLContextHelper* GLContextHelper::contextHelper = 0;
57 
58 namespace {
59 
resourceForContext(const QByteArray & resource)60 inline void *resourceForContext(const QByteArray &resource)
61 {
62 #if QT_CONFIG(opengl)
63     QOpenGLContext *shareContext = qt_gl_global_share_context();
64     if (!shareContext) {
65         qFatal("QWebEngine: OpenGL resource sharing is not set up in QtQuick. Please make sure to call QtWebEngine::initialize() in your main() function.");
66     }
67     return qApp->platformNativeInterface()->nativeResourceForContext(resource, shareContext);
68 #else
69     return nullptr;
70 #endif
71 }
72 
resourceForIntegration(const QByteArray & resource)73 inline void *resourceForIntegration(const QByteArray &resource)
74 {
75     return qApp->platformNativeInterface()->nativeResourceForIntegration(resource);
76 }
77 
78 }
79 
initialize()80 void GLContextHelper::initialize()
81 {
82     if (!contextHelper)
83         contextHelper = new GLContextHelper;
84 #if QT_CONFIG(opengl)
85     if (QGuiApplication::platformName() == QLatin1String("offscreen")){
86         contextHelper->m_robustness = false;
87         return;
88     }
89 
90     if (QOpenGLContext *context = qt_gl_global_share_context())
91         contextHelper->m_robustness = context->format().testOption(QSurfaceFormat::ResetNotification);
92 #endif
93 }
94 
destroy()95 void GLContextHelper::destroy()
96 {
97     delete contextHelper;
98     contextHelper = 0;
99 }
100 
initializeContextOnBrowserThread(gl::GLContext * context,gl::GLSurface * surface,gl::GLContextAttribs attribs)101 bool GLContextHelper::initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs)
102 {
103     return context->Initialize(surface, attribs);
104 }
105 
initializeContext(gl::GLContext * context,gl::GLSurface * surface,gl::GLContextAttribs attribs)106 bool GLContextHelper::initializeContext(gl::GLContext* context, gl::GLSurface* surface, gl::GLContextAttribs attribs)
107 {
108     bool ret = false;
109     Qt::ConnectionType connType = (QThread::currentThread() == qApp->thread()) ? Qt::DirectConnection : Qt::BlockingQueuedConnection;
110     QMetaObject::invokeMethod(contextHelper, "initializeContextOnBrowserThread", connType,
111             Q_RETURN_ARG(bool, ret),
112             Q_ARG(gl::GLContext*, context),
113             Q_ARG(gl::GLSurface*, surface),
114             Q_ARG(gl::GLContextAttribs, attribs));
115     return ret;
116 }
117 
getEGLConfig()118 void* GLContextHelper::getEGLConfig()
119 {
120     QByteArray resource = QByteArrayLiteral("eglconfig");
121     return resourceForContext(resource);
122 }
123 
getGlXConfig()124 void* GLContextHelper::getGlXConfig()
125 {
126     QByteArray resource = QByteArrayLiteral("glxconfig");
127     return resourceForContext(resource);
128 }
129 
getEGLDisplay()130 void* GLContextHelper::getEGLDisplay()
131 {
132 #ifdef Q_OS_WIN
133     // Windows QPA plugin does not implement resourceForIntegration for "egldisplay".
134     // Use resourceForContext instead.
135     return resourceForContext(QByteArrayLiteral("egldisplay"));
136 #else
137     return resourceForIntegration(QByteArrayLiteral("egldisplay"));
138 #endif
139 }
140 
getXDisplay()141 void* GLContextHelper::getXDisplay()
142 {
143     QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface();
144     if (pni)
145         return pni->nativeResourceForScreen(QByteArrayLiteral("display"), qApp->primaryScreen());
146     return nullptr;
147 }
148 
getNativeDisplay()149 void* GLContextHelper::getNativeDisplay()
150 {
151     return resourceForIntegration(QByteArrayLiteral("nativedisplay"));
152 }
153 
getGlXGetProcAddress()154 QFunctionPointer GLContextHelper::getGlXGetProcAddress()
155 {
156      QFunctionPointer get_proc_address = nullptr;
157 #if QT_CONFIG(opengl)
158     if (QOpenGLContext *context = qt_gl_global_share_context()) {
159         get_proc_address = context->getProcAddress("glXGetProcAddress");
160     }
161 #endif
162     return get_proc_address;
163 }
164 
getEglGetProcAddress()165 QFunctionPointer GLContextHelper::getEglGetProcAddress()
166 {
167      QFunctionPointer get_proc_address = nullptr;
168 #if QT_CONFIG(opengl)
169     if (QOpenGLContext *context = qt_gl_global_share_context()) {
170         get_proc_address = context->getProcAddress("eglGetProcAddress");
171     }
172 #endif
173     return get_proc_address;
174 }
175 
isCreateContextRobustnessSupported()176 bool GLContextHelper::isCreateContextRobustnessSupported()
177 {
178     return contextHelper->m_robustness;
179 }
180 
181 QT_END_NAMESPACE
182 
183 #if defined(OS_WIN)
184 namespace gl {
185 namespace init {
186 
CreateGLContext(GLShareGroup * share_group,GLSurface * compatible_surface,const GLContextAttribs & attribs)187 scoped_refptr<GLContext> CreateGLContext(GLShareGroup* share_group,
188                                          GLSurface* compatible_surface,
189                                          const GLContextAttribs& attribs)
190 {
191     scoped_refptr<GLContext> context;
192     if (GetGLImplementation() == kGLImplementationDesktopGL) {
193         context = new GLContextWGL(share_group);
194         if (!context->Initialize(compatible_surface, attribs))
195             return nullptr;
196         return context;
197     } else {
198         context = new GLContextEGL(share_group);
199     }
200 
201     if (!GLContextHelper::initializeContext(context.get(), compatible_surface, attribs))
202         return nullptr;
203 
204     return context;
205 }
206 
207 }  // namespace init
208 }  // namespace gl
209 
210 #endif // defined(OS_WIN)
211