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