summaryrefslogtreecommitdiffstats
path: root/src/gui/opengl
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-07-08 15:48:46 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-07-13 22:07:46 +0200
commitee0198a0183ec2b0cd9ddc6663110cd8e40320aa (patch)
tree74cb7cc1bbd982200480f66dc1057f71f837675b /src/gui/opengl
parent70f7155fcc20e43f096a029889d8a8117e11f70d (diff)
Move eglconvenience to QtGui
Task-number: QTBUG-83255 Change-Id: I8a008d8906308dd73a0793db5b88d3a1b6fdaf5c Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/gui/opengl')
-rw-r--r--src/gui/opengl/platform/egl/egl.pri32
-rw-r--r--src/gui/opengl/platform/egl/qeglconvenience.cpp628
-rw-r--r--src/gui/opengl/platform/egl/qeglconvenience_p.h127
-rw-r--r--src/gui/opengl/platform/egl/qeglpbuffer.cpp108
-rw-r--r--src/gui/opengl/platform/egl/qeglpbuffer_p.h80
-rw-r--r--src/gui/opengl/platform/egl/qeglplatformcontext.cpp848
-rw-r--r--src/gui/opengl/platform/egl/qeglplatformcontext_p.h145
-rw-r--r--src/gui/opengl/platform/egl/qeglstreamconvenience.cpp123
-rw-r--r--src/gui/opengl/platform/egl/qeglstreamconvenience_p.h211
-rw-r--r--src/gui/opengl/platform/egl/qt_egl_p.h128
-rw-r--r--src/gui/opengl/platform/egl/qxlibeglintegration.cpp166
-rw-r--r--src/gui/opengl/platform/egl/qxlibeglintegration_p.h69
-rw-r--r--src/gui/opengl/platform/platform.pri2
13 files changed, 2667 insertions, 0 deletions
diff --git a/src/gui/opengl/platform/egl/egl.pri b/src/gui/opengl/platform/egl/egl.pri
new file mode 100644
index 0000000000..78d3cc2e54
--- /dev/null
+++ b/src/gui/opengl/platform/egl/egl.pri
@@ -0,0 +1,32 @@
+HEADERS += \
+ opengl/platform/egl/qeglconvenience_p.h \
+ opengl/platform/egl/qeglstreamconvenience_p.h \
+ opengl/platform/egl/qt_egl_p.h
+
+SOURCES += \
+ opengl/platform/egl/qeglconvenience.cpp \
+ opengl/platform/egl/qeglstreamconvenience.cpp
+
+qtConfig(opengl) {
+ HEADERS += \
+ opengl/platform/egl/qeglplatformcontext_p.h \
+ opengl/platform/egl/qeglpbuffer_p.h
+
+ SOURCES += \
+ opengl/platform/egl/qeglplatformcontext.cpp \
+ opengl/platform/egl/qeglpbuffer.cpp
+}
+
+qtConfig(egl_x11) {
+ HEADERS += \
+ opengl/platform/egl/qxlibeglintegration_p.h
+ SOURCES += \
+ opengl/platform/egl/qxlibeglintegration.cpp
+ QMAKE_USE_PRIVATE += xlib
+} else {
+ # Avoid X11 header collision, use generic EGL native types
+ DEFINES += QT_EGL_NO_X11
+}
+CONFIG += egl
+
+qtConfig(dlopen): QMAKE_USE_PRIVATE += libdl
diff --git a/src/gui/opengl/platform/egl/qeglconvenience.cpp b/src/gui/opengl/platform/egl/qeglconvenience.cpp
new file mode 100644
index 0000000000..6076498b3e
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qeglconvenience.cpp
@@ -0,0 +1,628 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtCore/qbytearray.h>
+#include <QtGui/qopenglcontext.h>
+
+#ifdef Q_OS_LINUX
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#endif
+#include <QtGui/private/qmath_p.h>
+
+#include "qeglconvenience_p.h"
+
+#ifndef EGL_OPENGL_ES3_BIT_KHR
+#define EGL_OPENGL_ES3_BIT_KHR 0x0040
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QList<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format)
+{
+ int redSize = format.redBufferSize();
+ int greenSize = format.greenBufferSize();
+ int blueSize = format.blueBufferSize();
+ int alphaSize = format.alphaBufferSize();
+ int depthSize = format.depthBufferSize();
+ int stencilSize = format.stencilBufferSize();
+ int sampleCount = format.samples();
+
+ QList<EGLint> configAttributes;
+
+ // Map default, unspecified values (-1) to 0. This is important due to sorting rule #3
+ // in section 3.4.1 of the spec and allows picking a potentially faster 16-bit config
+ // over 32-bit ones when there is no explicit request for the color channel sizes:
+ //
+ // The red/green/blue sizes have a sort priority of 3, so they are sorted by
+ // first. (unless a caveat like SLOW or NON_CONFORMANT is present) The sort order is
+ // Special and described as "by larger _total_ number of color bits.". So EGL will put
+ // 32-bit configs in the list before the 16-bit configs. However, the spec also goes
+ // on to say "If the requested number of bits in attrib_list for a particular
+ // component is 0, then the number of bits for that component is not considered". This
+ // part of the spec also seems to imply that setting the red/green/blue bits to zero
+ // means none of the components are considered and EGL disregards the entire sorting
+ // rule. It then looks to the next highest priority rule, which is
+ // EGL_BUFFER_SIZE. Despite the selection criteria being "AtLeast" for
+ // EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are put in the
+ // list before 32-bit configs.
+ //
+ // This also means that explicitly specifying a size like 565 will still result in
+ // having larger (888) configs first in the returned list. We need to handle this
+ // ourselves later by manually filtering the list, instead of just blindly taking the
+ // first config from it.
+
+ configAttributes.append(EGL_RED_SIZE);
+ configAttributes.append(redSize > 0 ? redSize : 0);
+
+ configAttributes.append(EGL_GREEN_SIZE);
+ configAttributes.append(greenSize > 0 ? greenSize : 0);
+
+ configAttributes.append(EGL_BLUE_SIZE);
+ configAttributes.append(blueSize > 0 ? blueSize : 0);
+
+ configAttributes.append(EGL_ALPHA_SIZE);
+ configAttributes.append(alphaSize > 0 ? alphaSize : 0);
+
+ configAttributes.append(EGL_SAMPLES);
+ configAttributes.append(sampleCount > 0 ? sampleCount : 0);
+
+ configAttributes.append(EGL_SAMPLE_BUFFERS);
+ configAttributes.append(sampleCount > 0);
+
+ if (format.renderableType() != QSurfaceFormat::OpenVG) {
+ configAttributes.append(EGL_DEPTH_SIZE);
+ configAttributes.append(depthSize > 0 ? depthSize : 0);
+
+ configAttributes.append(EGL_STENCIL_SIZE);
+ configAttributes.append(stencilSize > 0 ? stencilSize : 0);
+ } else {
+ // OpenVG needs alpha mask for clipping
+ configAttributes.append(EGL_ALPHA_MASK_SIZE);
+ configAttributes.append(8);
+ }
+
+ return configAttributes;
+}
+
+bool q_reduceConfigAttributes(QList<EGLint> *configAttributes)
+{
+ int i = -1;
+ // Reduce the complexity of a configuration request to ask for less
+ // because the previous request did not result in success. Returns
+ // true if the complexity was reduced, or false if no further
+ // reductions in complexity are possible.
+
+ i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
+ }
+
+#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
+ // For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't
+ // find a config which supports pre-multiplied formats, remove the flag on the surface type:
+
+ i = configAttributes->indexOf(EGL_SURFACE_TYPE);
+ if (i >= 0) {
+ EGLint surfaceType = configAttributes->at(i +1);
+ if (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) {
+ surfaceType ^= EGL_VG_ALPHA_FORMAT_PRE_BIT;
+ configAttributes->replace(i+1,surfaceType);
+ return true;
+ }
+ }
+#endif
+
+ // EGL chooses configs with the highest color depth over
+ // those with smaller (but faster) lower color depths. One
+ // way around this is to set EGL_BUFFER_SIZE to 16, which
+ // trumps the others. Of course, there may not be a 16-bit
+ // config available, so it's the first restraint we remove.
+ i = configAttributes->indexOf(EGL_BUFFER_SIZE);
+ if (i >= 0) {
+ if (configAttributes->at(i+1) == 16) {
+ configAttributes->remove(i,2);
+ return true;
+ }
+ }
+
+ i = configAttributes->indexOf(EGL_SAMPLES);
+ if (i >= 0) {
+ EGLint value = configAttributes->value(i+1, 0);
+ if (value > 1)
+ configAttributes->replace(i+1, qMin(EGLint(16), value / 2));
+ else
+ configAttributes->remove(i, 2);
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_DEPTH_SIZE);
+ if (i >= 0) {
+ if (configAttributes->at(i + 1) >= 32)
+ configAttributes->replace(i + 1, 24);
+ else if (configAttributes->at(i + 1) > 1)
+ configAttributes->replace(i + 1, 1);
+ else
+ configAttributes->remove(i, 2);
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_ALPHA_SIZE);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
+#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB)
+ i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGBA);
+ if (i >= 0) {
+ configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB);
+ configAttributes->replace(i+1,true);
+
+ }
+#endif
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_STENCIL_SIZE);
+ if (i >= 0) {
+ if (configAttributes->at(i + 1) > 1)
+ configAttributes->replace(i + 1, 1);
+ else
+ configAttributes->remove(i, 2);
+ return true;
+ }
+
+#ifdef EGL_BIND_TO_TEXTURE_RGB
+ i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+QEglConfigChooser::QEglConfigChooser(EGLDisplay display)
+ : m_display(display)
+ , m_surfaceType(EGL_WINDOW_BIT)
+ , m_ignore(false)
+ , m_confAttrRed(0)
+ , m_confAttrGreen(0)
+ , m_confAttrBlue(0)
+ , m_confAttrAlpha(0)
+{
+}
+
+QEglConfigChooser::~QEglConfigChooser()
+{
+}
+
+EGLConfig QEglConfigChooser::chooseConfig()
+{
+ QList<EGLint> configureAttributes = q_createConfigAttributesFromFormat(m_format);
+ configureAttributes.append(EGL_SURFACE_TYPE);
+ configureAttributes.append(surfaceType());
+
+ configureAttributes.append(EGL_RENDERABLE_TYPE);
+ bool needsES2Plus = false;
+ switch (m_format.renderableType()) {
+ case QSurfaceFormat::OpenVG:
+ configureAttributes.append(EGL_OPENVG_BIT);
+ break;
+#ifdef EGL_VERSION_1_4
+ case QSurfaceFormat::DefaultRenderableType:
+#ifndef QT_NO_OPENGL
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL)
+ configureAttributes.append(EGL_OPENGL_BIT);
+ else
+#endif // QT_NO_OPENGL
+ needsES2Plus = true;
+ break;
+ case QSurfaceFormat::OpenGL:
+ configureAttributes.append(EGL_OPENGL_BIT);
+ break;
+#endif
+ case QSurfaceFormat::OpenGLES:
+ if (m_format.majorVersion() == 1) {
+ configureAttributes.append(EGL_OPENGL_ES_BIT);
+ break;
+ }
+ Q_FALLTHROUGH();
+ default:
+ needsES2Plus = true;
+ break;
+ }
+ if (needsES2Plus) {
+ if (m_format.majorVersion() >= 3 && q_hasEglExtension(display(), "EGL_KHR_create_context"))
+ configureAttributes.append(EGL_OPENGL_ES3_BIT_KHR);
+ else
+ configureAttributes.append(EGL_OPENGL_ES2_BIT);
+ }
+ configureAttributes.append(EGL_NONE);
+
+ EGLConfig cfg = nullptr;
+ do {
+ // Get the number of matching configurations for this set of properties.
+ EGLint matching = 0;
+ if (!eglChooseConfig(display(), configureAttributes.constData(), nullptr, 0, &matching) || !matching)
+ continue;
+
+ // Fetch all of the matching configurations and find the
+ // first that matches the pixel format we wanted.
+ int i = configureAttributes.indexOf(EGL_RED_SIZE);
+ m_confAttrRed = configureAttributes.at(i+1);
+ i = configureAttributes.indexOf(EGL_GREEN_SIZE);
+ m_confAttrGreen = configureAttributes.at(i+1);
+ i = configureAttributes.indexOf(EGL_BLUE_SIZE);
+ m_confAttrBlue = configureAttributes.at(i+1);
+ i = configureAttributes.indexOf(EGL_ALPHA_SIZE);
+ m_confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1);
+
+ QList<EGLConfig> configs(matching);
+ eglChooseConfig(display(), configureAttributes.constData(), configs.data(), configs.size(), &matching);
+ if (!cfg && matching > 0)
+ cfg = configs.first();
+
+ // Filter the list. Due to the EGL sorting rules configs with higher depth are
+ // placed first when the minimum color channel sizes have been specified (i.e. the
+ // QSurfaceFormat contains color sizes > 0). To prevent returning a 888 config
+ // when the QSurfaceFormat explicitly asked for 565, go through the returned
+ // configs and look for one that exactly matches the requested sizes. When no
+ // sizes have been given, take the first, which will be a config with the smaller
+ // (e.g. 16-bit) depth.
+ for (int i = 0; i < configs.size(); ++i) {
+ if (filterConfig(configs[i]))
+ return configs.at(i);
+ }
+ } while (q_reduceConfigAttributes(&configureAttributes));
+
+ if (!cfg)
+ qWarning("Cannot find EGLConfig, returning null config");
+ return cfg;
+}
+
+bool QEglConfigChooser::filterConfig(EGLConfig config) const
+{
+ // If we are fine with the highest depth (e.g. RGB888 configs) even when something
+ // smaller (565) was explicitly requested, do nothing.
+ if (m_ignore)
+ return true;
+
+ EGLint red = 0;
+ EGLint green = 0;
+ EGLint blue = 0;
+ EGLint alpha = 0;
+
+ // Compare only if a size was given. Otherwise just accept.
+ if (m_confAttrRed)
+ eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &red);
+ if (m_confAttrGreen)
+ eglGetConfigAttrib(display(), config, EGL_GREEN_SIZE, &green);
+ if (m_confAttrBlue)
+ eglGetConfigAttrib(display(), config, EGL_BLUE_SIZE, &blue);
+ if (m_confAttrAlpha)
+ eglGetConfigAttrib(display(), config, EGL_ALPHA_SIZE, &alpha);
+
+ return red == m_confAttrRed && green == m_confAttrGreen
+ && blue == m_confAttrBlue && alpha == m_confAttrAlpha;
+}
+
+EGLConfig q_configFromGLFormat(EGLDisplay display, const QSurfaceFormat &format, bool highestPixelFormat, int surfaceType)
+{
+ QEglConfigChooser chooser(display);
+ chooser.setSurfaceFormat(format);
+ chooser.setSurfaceType(surfaceType);
+ chooser.setIgnoreColorChannels(highestPixelFormat);
+
+ return chooser.chooseConfig();
+}
+
+QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, const QSurfaceFormat &referenceFormat)
+{
+ QSurfaceFormat format;
+ EGLint redSize = 0;
+ EGLint greenSize = 0;
+ EGLint blueSize = 0;
+ EGLint alphaSize = 0;
+ EGLint depthSize = 0;
+ EGLint stencilSize = 0;
+ EGLint sampleCount = 0;
+ EGLint renderableType = 0;
+
+ eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
+ eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
+ eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
+ eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize);
+ eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize);
+ eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize);
+ eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount);
+ eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType);
+
+ if (referenceFormat.renderableType() == QSurfaceFormat::OpenVG && (renderableType & EGL_OPENVG_BIT))
+ format.setRenderableType(QSurfaceFormat::OpenVG);
+#ifdef EGL_VERSION_1_4
+ else if (referenceFormat.renderableType() == QSurfaceFormat::OpenGL
+ && (renderableType & EGL_OPENGL_BIT))
+ format.setRenderableType(QSurfaceFormat::OpenGL);
+ else if (referenceFormat.renderableType() == QSurfaceFormat::DefaultRenderableType
+#ifndef QT_NO_OPENGL
+ && QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL
+#endif
+ && (renderableType & EGL_OPENGL_BIT))
+ format.setRenderableType(QSurfaceFormat::OpenGL);
+#endif
+ else
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+
+ format.setRedBufferSize(redSize);
+ format.setGreenBufferSize(greenSize);
+ format.setBlueBufferSize(blueSize);
+ format.setAlphaBufferSize(alphaSize);
+ format.setDepthBufferSize(depthSize);
+ format.setStencilBufferSize(stencilSize);
+ format.setSamples(sampleCount);
+ format.setStereo(false); // EGL doesn't support stereo buffers
+ format.setSwapInterval(referenceFormat.swapInterval());
+
+ // Clear the EGL error state because some of the above may
+ // have errored out because the attribute is not applicable
+ // to the surface type. Such errors don't matter.
+ eglGetError();
+
+ return format;
+}
+
+bool q_hasEglExtension(EGLDisplay display, const char* extensionName)
+{
+ QList<QByteArray> extensions =
+ QByteArray(reinterpret_cast<const char *>
+ (eglQueryString(display, EGL_EXTENSIONS))).split(' ');
+ return extensions.contains(extensionName);
+}
+
+struct AttrInfo { EGLint attr; const char *name; };
+static struct AttrInfo attrs[] = {
+ {EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE"},
+ {EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE"},
+ {EGL_BLUE_SIZE, "EGL_BLUE_SIZE"},
+ {EGL_GREEN_SIZE, "EGL_GREEN_SIZE"},
+ {EGL_RED_SIZE, "EGL_RED_SIZE"},
+ {EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE"},
+ {EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE"},
+ {EGL_CONFIG_CAVEAT, "EGL_CONFIG_CAVEAT"},
+ {EGL_CONFIG_ID, "EGL_CONFIG_ID"},
+ {EGL_LEVEL, "EGL_LEVEL"},
+ {EGL_MAX_PBUFFER_HEIGHT, "EGL_MAX_PBUFFER_HEIGHT"},
+ {EGL_MAX_PBUFFER_PIXELS, "EGL_MAX_PBUFFER_PIXELS"},
+ {EGL_MAX_PBUFFER_WIDTH, "EGL_MAX_PBUFFER_WIDTH"},
+ {EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE"},
+ {EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID"},
+ {EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE"},
+ {EGL_SAMPLES, "EGL_SAMPLES"},
+ {EGL_SAMPLE_BUFFERS, "EGL_SAMPLE_BUFFERS"},
+ {EGL_SURFACE_TYPE, "EGL_SURFACE_TYPE"},
+ {EGL_TRANSPARENT_TYPE, "EGL_TRANSPARENT_TYPE"},
+ {EGL_TRANSPARENT_BLUE_VALUE, "EGL_TRANSPARENT_BLUE_VALUE"},
+ {EGL_TRANSPARENT_GREEN_VALUE, "EGL_TRANSPARENT_GREEN_VALUE"},
+ {EGL_TRANSPARENT_RED_VALUE, "EGL_TRANSPARENT_RED_VALUE"},
+ {EGL_BIND_TO_TEXTURE_RGB, "EGL_BIND_TO_TEXTURE_RGB"},
+ {EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA"},
+ {EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL"},
+ {EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL"},
+ {-1, nullptr}};
+
+void q_printEglConfig(EGLDisplay display, EGLConfig config)
+{
+ EGLint index;
+ for (index = 0; attrs[index].attr != -1; ++index) {
+ EGLint value;
+ if (eglGetConfigAttrib(display, config, attrs[index].attr, &value)) {
+ qDebug("\t%s: %d", attrs[index].name, (int)value);
+ }
+ }
+}
+
+#ifdef Q_OS_UNIX
+
+QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize)
+{
+#ifndef Q_OS_LINUX
+ Q_UNUSED(framebufferDevice);
+#endif
+ const int defaultPhysicalDpi = 100;
+ static QSizeF size;
+
+ if (size.isEmpty()) {
+ // Note: in millimeters
+ int width = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH");
+ int height = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT");
+
+ if (width && height) {
+ size.setWidth(width);
+ size.setHeight(height);
+ return size;
+ }
+
+ int w = -1;
+ int h = -1;
+ QSize screenResolution;
+#ifdef Q_OS_LINUX
+ struct fb_var_screeninfo vinfo;
+
+ if (framebufferDevice != -1) {
+ if (ioctl(framebufferDevice, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+ qWarning("eglconvenience: Could not query screen info");
+ } else {
+ w = vinfo.width;
+ h = vinfo.height;
+ screenResolution = QSize(vinfo.xres, vinfo.yres);
+ }
+ } else
+#endif
+ {
+ // Use the provided screen size, when available, since some platforms may have their own
+ // specific way to query it. Otherwise try querying it from the framebuffer.
+ screenResolution = screenSize.isEmpty() ? q_screenSizeFromFb(framebufferDevice) : screenSize;
+ }
+
+ size.setWidth(w <= 0 ? screenResolution.width() * Q_MM_PER_INCH / defaultPhysicalDpi : qreal(w));
+ size.setHeight(h <= 0 ? screenResolution.height() * Q_MM_PER_INCH / defaultPhysicalDpi : qreal(h));
+
+ if (w <= 0 || h <= 0)
+ qWarning("Unable to query physical screen size, defaulting to %d dpi.\n"
+ "To override, set QT_QPA_EGLFS_PHYSICAL_WIDTH "
+ "and QT_QPA_EGLFS_PHYSICAL_HEIGHT (in millimeters).", defaultPhysicalDpi);
+ }
+
+ return size;
+}
+
+QSize q_screenSizeFromFb(int framebufferDevice)
+{
+#ifndef Q_OS_LINUX
+ Q_UNUSED(framebufferDevice);
+#endif
+ const int defaultWidth = 800;
+ const int defaultHeight = 600;
+ static QSize size;
+
+ if (size.isEmpty()) {
+ int width = qEnvironmentVariableIntValue("QT_QPA_EGLFS_WIDTH");
+ int height = qEnvironmentVariableIntValue("QT_QPA_EGLFS_HEIGHT");
+
+ if (width && height) {
+ size.setWidth(width);
+ size.setHeight(height);
+ return size;
+ }
+
+#ifdef Q_OS_LINUX
+ struct fb_var_screeninfo vinfo;
+ int xres = -1;
+ int yres = -1;
+
+ if (framebufferDevice != -1) {
+ if (ioctl(framebufferDevice, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+ qWarning("eglconvenience: Could not read screen info");
+ } else {
+ xres = vinfo.xres;
+ yres = vinfo.yres;
+ }
+ }
+
+ size.setWidth(xres <= 0 ? defaultWidth : xres);
+ size.setHeight(yres <= 0 ? defaultHeight : yres);
+#else
+ size.setWidth(defaultWidth);
+ size.setHeight(defaultHeight);
+#endif
+ }
+
+ return size;
+}
+
+int q_screenDepthFromFb(int framebufferDevice)
+{
+#ifndef Q_OS_LINUX
+ Q_UNUSED(framebufferDevice);
+#endif
+ const int defaultDepth = 32;
+ static int depth = qEnvironmentVariableIntValue("QT_QPA_EGLFS_DEPTH");
+
+ if (depth == 0) {
+#ifdef Q_OS_LINUX
+ struct fb_var_screeninfo vinfo;
+
+ if (framebufferDevice != -1) {
+ if (ioctl(framebufferDevice, FBIOGET_VSCREENINFO, &vinfo) == -1)
+ qWarning("eglconvenience: Could not query screen info");
+ else
+ depth = vinfo.bits_per_pixel;
+ }
+
+ if (depth <= 0)
+ depth = defaultDepth;
+#else
+ depth = defaultDepth;
+#endif
+ }
+
+ return depth;
+}
+
+qreal q_refreshRateFromFb(int framebufferDevice)
+{
+#ifndef Q_OS_LINUX
+ Q_UNUSED(framebufferDevice);
+#endif
+
+ static qreal rate = 0;
+
+#ifdef Q_OS_LINUX
+ if (rate == 0) {
+ if (framebufferDevice != -1) {
+ struct fb_var_screeninfo vinfo;
+ if (ioctl(framebufferDevice, FBIOGET_VSCREENINFO, &vinfo) != -1) {
+ const quint64 quot = quint64(vinfo.left_margin + vinfo.right_margin + vinfo.xres + vinfo.hsync_len)
+ * quint64(vinfo.upper_margin + vinfo.lower_margin + vinfo.yres + vinfo.vsync_len)
+ * vinfo.pixclock;
+ if (quot)
+ rate = 1000000000000LLU / quot;
+ } else {
+ qWarning("eglconvenience: Could not query screen info");
+ }
+ }
+ }
+#endif
+
+ if (rate == 0)
+ rate = 60;
+
+ return rate;
+}
+
+#endif // Q_OS_UNIX
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/platform/egl/qeglconvenience_p.h b/src/gui/opengl/platform/egl/qeglconvenience_p.h
new file mode 100644
index 0000000000..7675d1316a
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qeglconvenience_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLCONVENIENCE_H
+#define QEGLCONVENIENCE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qsurfaceformat.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qsize.h>
+
+#include <QtGui/private/qt_egl_p.h>
+
+
+QT_BEGIN_NAMESPACE
+
+Q_GUI_EXPORT QList<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format);
+
+Q_GUI_EXPORT bool q_reduceConfigAttributes(QList<EGLint> *configAttributes);
+
+Q_GUI_EXPORT EGLConfig q_configFromGLFormat(EGLDisplay display,
+ const QSurfaceFormat &format,
+ bool highestPixelFormat = false,
+ int surfaceType = EGL_WINDOW_BIT);
+
+Q_GUI_EXPORT QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config,
+ const QSurfaceFormat &referenceFormat = {});
+
+Q_GUI_EXPORT bool q_hasEglExtension(EGLDisplay display,const char* extensionName);
+
+Q_GUI_EXPORT void q_printEglConfig(EGLDisplay display, EGLConfig config);
+
+#ifdef Q_OS_UNIX
+Q_GUI_EXPORT QSizeF q_physicalScreenSizeFromFb(int framebufferDevice,
+ const QSize &screenSize = {});
+
+Q_GUI_EXPORT QSize q_screenSizeFromFb(int framebufferDevice);
+
+Q_GUI_EXPORT int q_screenDepthFromFb(int framebufferDevice);
+
+Q_GUI_EXPORT qreal q_refreshRateFromFb(int framebufferDevice);
+
+#endif
+
+class Q_GUI_EXPORT QEglConfigChooser
+{
+public:
+ QEglConfigChooser(EGLDisplay display);
+ virtual ~QEglConfigChooser();
+
+ EGLDisplay display() const { return m_display; }
+
+ void setSurfaceType(EGLint surfaceType) { m_surfaceType = surfaceType; }
+ EGLint surfaceType() const { return m_surfaceType; }
+
+ void setSurfaceFormat(const QSurfaceFormat &format) { m_format = format; }
+ QSurfaceFormat surfaceFormat() const { return m_format; }
+
+ void setIgnoreColorChannels(bool ignore) { m_ignore = ignore; }
+ bool ignoreColorChannels() const { return m_ignore; }
+
+ EGLConfig chooseConfig();
+
+protected:
+ virtual bool filterConfig(EGLConfig config) const;
+
+ QSurfaceFormat m_format;
+ EGLDisplay m_display;
+ EGLint m_surfaceType;
+ bool m_ignore;
+
+ int m_confAttrRed;
+ int m_confAttrGreen;
+ int m_confAttrBlue;
+ int m_confAttrAlpha;
+};
+
+
+QT_END_NAMESPACE
+
+#endif //QEGLCONVENIENCE_H
diff --git a/src/gui/opengl/platform/egl/qeglpbuffer.cpp b/src/gui/opengl/platform/egl/qeglpbuffer.cpp
new file mode 100644
index 0000000000..55e199a6ad
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qeglpbuffer.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qoffscreensurface.h>
+#include "qeglpbuffer_p.h"
+#include "qeglconvenience_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEGLPbuffer
+ \brief A pbuffer-based implementation of QPlatformOffscreenSurface for EGL.
+ \since 5.2
+ \internal
+ \ingroup qpa
+
+ To use this implementation in the platform plugin simply
+ reimplement QPlatformIntegration::createPlatformOffscreenSurface()
+ and return a new instance of this class.
+*/
+
+QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface,
+ QEGLPlatformContext::Flags flags)
+ : QPlatformOffscreenSurface(offscreenSurface)
+ , m_format(format)
+ , m_display(display)
+ , m_pbuffer(EGL_NO_SURFACE)
+{
+ m_hasSurfaceless = !flags.testFlag(QEGLPlatformContext::NoSurfaceless)
+ && q_hasEglExtension(display, "EGL_KHR_surfaceless_context");
+
+ // Disable surfaceless contexts on Mesa for now. As of 10.6.0 and Intel at least, some
+ // operations (glReadPixels) are unable to work without a surface since they at some
+ // point temporarily unbind the current FBO and then later blow up in some seemingly
+ // safe operations, like setting the viewport, that apparently need access to the
+ // read/draw surface in the Intel backend.
+ const char *vendor = eglQueryString(display, EGL_VENDOR); // hard to check for GL_ strings here, so blacklist all Mesa
+ if (vendor && strstr(vendor, "Mesa"))
+ m_hasSurfaceless = false;
+
+ if (m_hasSurfaceless)
+ return;
+
+ EGLConfig config = q_configFromGLFormat(m_display, m_format, false, EGL_PBUFFER_BIT);
+
+ if (config) {
+ const EGLint attributes[] = {
+ EGL_WIDTH, offscreenSurface->size().width(),
+ EGL_HEIGHT, offscreenSurface->size().height(),
+ EGL_LARGEST_PBUFFER, EGL_FALSE,
+ EGL_NONE
+ };
+
+ m_pbuffer = eglCreatePbufferSurface(m_display, config, attributes);
+
+ if (m_pbuffer != EGL_NO_SURFACE)
+ m_format = q_glFormatFromConfig(m_display, config);
+ }
+}
+
+QEGLPbuffer::~QEGLPbuffer()
+{
+ if (m_pbuffer != EGL_NO_SURFACE)
+ eglDestroySurface(m_display, m_pbuffer);
+}
+
+bool QEGLPbuffer::isValid() const
+{
+ return m_pbuffer != EGL_NO_SURFACE || m_hasSurfaceless;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/platform/egl/qeglpbuffer_p.h b/src/gui/opengl/platform/egl/qeglpbuffer_p.h
new file mode 100644
index 0000000000..370c430f38
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qeglpbuffer_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLPBUFFER_H
+#define QEGLPBUFFER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qpa/qplatformoffscreensurface.h>
+#include <QtGui/private/qeglplatformcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QEGLPbuffer : public QPlatformOffscreenSurface
+{
+public:
+ QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface,
+ QEGLPlatformContext::Flags flags = { });
+ ~QEGLPbuffer();
+
+ QSurfaceFormat format() const override { return m_format; }
+ bool isValid() const override;
+
+ EGLSurface pbuffer() const { return m_pbuffer; }
+
+private:
+ QSurfaceFormat m_format;
+ EGLDisplay m_display;
+ EGLSurface m_pbuffer;
+ bool m_hasSurfaceless;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLPBUFFER_H
diff --git a/src/gui/opengl/platform/egl/qeglplatformcontext.cpp b/src/gui/opengl/platform/egl/qeglplatformcontext.cpp
new file mode 100644
index 0000000000..561079b48f
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qeglplatformcontext.cpp
@@ -0,0 +1,848 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglplatformcontext_p.h"
+#include "qeglconvenience_p.h"
+#include "qeglpbuffer_p.h"
+#include <qpa/qplatformwindow.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtCore/qdebug.h>
+
+#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#include <QtCore/private/qjnihelpers_p.h>
+#endif
+#ifndef Q_OS_WIN
+#include <dlfcn.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEGLPlatformContext
+ \brief An EGL context implementation.
+ \since 5.2
+ \internal
+ \ingroup qpa
+
+ Implement QPlatformOpenGLContext using EGL. To use it in platform
+ plugins a subclass must be created since
+ eglSurfaceForPlatformSurface() has to be reimplemented. This
+ function is used for mapping platform surfaces (windows) to EGL
+ surfaces and is necessary since different platform plugins may
+ have different ways of handling native windows (for example, a
+ plugin may choose not to back every platform window by a real EGL
+ surface). Other than that, no further customization is necessary.
+ */
+
+// Constants from EGL_KHR_create_context
+#ifndef EGL_CONTEXT_MINOR_VERSION_KHR
+#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
+#endif
+#ifndef EGL_CONTEXT_FLAGS_KHR
+#define EGL_CONTEXT_FLAGS_KHR 0x30FC
+#endif
+#ifndef EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
+#endif
+#ifndef EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
+#endif
+#ifndef EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#endif
+#ifndef EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#endif
+#ifndef EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#endif
+
+// Constants for OpenGL which are not available in the ES headers.
+#ifndef GL_CONTEXT_FLAGS
+#define GL_CONTEXT_FLAGS 0x821E
+#endif
+#ifndef GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
+#endif
+#ifndef GL_CONTEXT_FLAG_DEBUG_BIT
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#endif
+#ifndef GL_CONTEXT_PROFILE_MASK
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#endif
+#ifndef GL_CONTEXT_CORE_PROFILE_BIT
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#endif
+#ifndef GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#endif
+
+QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
+ EGLConfig *config, Flags flags)
+ : m_eglDisplay(display)
+ , m_flags(flags)
+ , m_ownsContext(true)
+{
+ m_eglConfig = config ? *config : q_configFromGLFormat(display, format);
+
+ m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig, format);
+ // m_format now has the renderableType() resolved (it cannot be Default anymore)
+ // but does not yet contain version, profile, options.
+ m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : nullptr;
+
+ QList<EGLint> contextAttrs;
+ contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
+ contextAttrs.append(format.majorVersion());
+ const bool hasKHRCreateContext = q_hasEglExtension(m_eglDisplay, "EGL_KHR_create_context");
+ if (hasKHRCreateContext) {
+ contextAttrs.append(EGL_CONTEXT_MINOR_VERSION_KHR);
+ contextAttrs.append(format.minorVersion());
+ int flags = 0;
+ // The debug bit is supported both for OpenGL and OpenGL ES.
+ if (format.testOption(QSurfaceFormat::DebugContext))
+ flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
+ // The fwdcompat bit is only for OpenGL 3.0+.
+ if (m_format.renderableType() == QSurfaceFormat::OpenGL
+ && format.majorVersion() >= 3
+ && !format.testOption(QSurfaceFormat::DeprecatedFunctions))
+ flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
+ if (flags) {
+ contextAttrs.append(EGL_CONTEXT_FLAGS_KHR);
+ contextAttrs.append(flags);
+ }
+ // Profiles are OpenGL only and mandatory in 3.2+. The value is silently ignored for < 3.2.
+ if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
+ contextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
+ contextAttrs.append(format.profile() == QSurfaceFormat::CoreProfile
+ ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
+ : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
+ }
+ }
+
+ // Special Options for OpenVG surfaces
+ if (m_format.renderableType() == QSurfaceFormat::OpenVG) {
+ contextAttrs.append(EGL_ALPHA_MASK_SIZE);
+ contextAttrs.append(8);
+ }
+
+ contextAttrs.append(EGL_NONE);
+ m_contextAttrs = contextAttrs;
+
+ switch (m_format.renderableType()) {
+ case QSurfaceFormat::OpenVG:
+ m_api = EGL_OPENVG_API;
+ break;
+#ifdef EGL_VERSION_1_4
+ case QSurfaceFormat::OpenGL:
+ m_api = EGL_OPENGL_API;
+ break;
+#endif // EGL_VERSION_1_4
+ default:
+ m_api = EGL_OPENGL_ES_API;
+ break;
+ }
+
+ eglBindAPI(m_api);
+ m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData());
+ if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) {
+ m_shareContext = nullptr;
+ m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, nullptr, contextAttrs.constData());
+ }
+
+ if (m_eglContext == EGL_NO_CONTEXT) {
+ qWarning("QEGLPlatformContext: Failed to create context: %x", eglGetError());
+ return;
+ }
+
+ static const bool printConfig = qEnvironmentVariableIntValue("QT_QPA_EGLFS_DEBUG");
+ if (printConfig) {
+ qDebug() << "Created context for format" << format << "with config:";
+ q_printEglConfig(m_eglDisplay, m_eglConfig);
+ }
+
+ // Cannot just call updateFormatFromGL() since it relies on virtuals. Defer it to initialize().
+}
+
+void QEGLPlatformContext::adopt(EGLContext context, EGLDisplay display, QPlatformOpenGLContext *share)
+{
+ Q_ASSERT(!m_ownsContext);
+
+ m_eglDisplay = display;
+
+ // Figure out the EGLConfig.
+ EGLint value = 0;
+ eglQueryContext(m_eglDisplay, context, EGL_CONFIG_ID, &value);
+ EGLint n = 0;
+ EGLConfig cfg;
+ const EGLint attribs[] = { EGL_CONFIG_ID, value, EGL_NONE };
+ if (eglChooseConfig(m_eglDisplay, attribs, &cfg, 1, &n) && n == 1) {
+ m_eglConfig = cfg;
+ m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig);
+ } else {
+ qWarning("QEGLPlatformContext: Failed to get framebuffer configuration for context");
+ }
+
+ // Fetch client API type.
+ value = 0;
+ eglQueryContext(m_eglDisplay, context, EGL_CONTEXT_CLIENT_TYPE, &value);
+ if (value == EGL_OPENGL_API || value == EGL_OPENGL_ES_API) {
+ // if EGL config supports both OpenGL and OpenGL ES render type,
+ // q_glFormatFromConfig() with the default "referenceFormat" parameter
+ // will always figure it out as OpenGL render type.
+ // We can override it to match user's real render type.
+ if (value == EGL_OPENGL_ES_API)
+ m_format.setRenderableType(QSurfaceFormat::OpenGLES);
+ m_api = value;
+ eglBindAPI(m_api);
+ } else {
+ qWarning("QEGLPlatformContext: Failed to get client API type");
+ m_api = EGL_OPENGL_ES_API;
+ }
+
+ m_eglContext = context;
+ m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : nullptr;
+ updateFormatFromGL();
+}
+
+void QEGLPlatformContext::initialize()
+{
+ if (m_eglContext != EGL_NO_CONTEXT)
+ updateFormatFromGL();
+}
+
+// Base implementation for pbuffers. Subclasses will handle the specialized cases for
+// platforms without pbuffers.
+EGLSurface QEGLPlatformContext::createTemporaryOffscreenSurface()
+{
+ // Make the context current to ensure the GL version query works. This needs a surface too.
+ const EGLint pbufferAttributes[] = {
+ EGL_WIDTH, 1,
+ EGL_HEIGHT, 1,
+ EGL_LARGEST_PBUFFER, EGL_FALSE,
+ EGL_NONE
+ };
+
+ // Cannot just pass m_eglConfig because it may not be suitable for pbuffers. Instead,
+ // do what QEGLPbuffer would do: request a config with the same attributes but with
+ // PBUFFER_BIT set.
+ EGLConfig config = q_configFromGLFormat(m_eglDisplay, m_format, false, EGL_PBUFFER_BIT);
+
+ return eglCreatePbufferSurface(m_eglDisplay, config, pbufferAttributes);
+}
+
+void QEGLPlatformContext::destroyTemporaryOffscreenSurface(EGLSurface surface)
+{
+ eglDestroySurface(m_eglDisplay, surface);
+}
+
+void QEGLPlatformContext::runGLChecks()
+{
+ // Nothing to do here, subclasses may override in order to perform OpenGL
+ // queries needing a context.
+}
+
+void QEGLPlatformContext::updateFormatFromGL()
+{
+#ifndef QT_NO_OPENGL
+ // Have to save & restore to prevent QOpenGLContext::currentContext() from becoming
+ // inconsistent after QOpenGLContext::create().
+ EGLDisplay prevDisplay = eglGetCurrentDisplay();
+ if (prevDisplay == EGL_NO_DISPLAY) // when no context is current
+ prevDisplay = m_eglDisplay;
+ EGLContext prevContext = eglGetCurrentContext();
+ EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW);
+ EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ);
+
+ // Rely on the surfaceless extension, if available. This is beneficial since we can
+ // avoid creating an extra pbuffer surface which is apparently troublesome with some
+ // drivers (Mesa) when certain attributes are present (multisampling).
+ EGLSurface tempSurface = EGL_NO_SURFACE;
+ EGLContext tempContext = EGL_NO_CONTEXT;
+ if (m_flags.testFlag(NoSurfaceless) || !q_hasEglExtension(m_eglDisplay, "EGL_KHR_surfaceless_context"))
+ tempSurface = createTemporaryOffscreenSurface();
+
+ EGLBoolean ok = eglMakeCurrent(m_eglDisplay, tempSurface, tempSurface, m_eglContext);
+ if (!ok) {
+ EGLConfig config = q_configFromGLFormat(m_eglDisplay, m_format, false, EGL_PBUFFER_BIT);
+ tempContext = eglCreateContext(m_eglDisplay, config, nullptr, m_contextAttrs.constData());
+ if (tempContext != EGL_NO_CONTEXT)
+ ok = eglMakeCurrent(m_eglDisplay, tempSurface, tempSurface, tempContext);
+ }
+ if (ok) {
+ if (m_format.renderableType() == QSurfaceFormat::OpenGL
+ || m_format.renderableType() == QSurfaceFormat::OpenGLES) {
+ const GLubyte *s = glGetString(GL_VERSION);
+ if (s) {
+ QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
+ int major, minor;
+ if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
+ m_format.setMajorVersion(major);
+ m_format.setMinorVersion(minor);
+ }
+ }
+ m_format.setProfile(QSurfaceFormat::NoProfile);
+ m_format.setOptions(QSurfaceFormat::FormatOptions());
+ if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
+ // Check profile and options.
+ if (m_format.majorVersion() < 3) {
+ m_format.setOption(QSurfaceFormat::DeprecatedFunctions);
+ } else {
+ GLint value = 0;
+ glGetIntegerv(GL_CONTEXT_FLAGS, &value);
+ if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
+ m_format.setOption(QSurfaceFormat::DeprecatedFunctions);
+ if (value & GL_CONTEXT_FLAG_DEBUG_BIT)
+ m_format.setOption(QSurfaceFormat::DebugContext);
+ if (m_format.version() >= qMakePair(3, 2)) {
+ value = 0;
+ glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
+ if (value & GL_CONTEXT_CORE_PROFILE_BIT)
+ m_format.setProfile(QSurfaceFormat::CoreProfile);
+ else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
+ m_format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ }
+ }
+ }
+ }
+ runGLChecks();
+ eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext);
+ } else {
+ qWarning("QEGLPlatformContext: Failed to make temporary surface current, format not updated (%x)", eglGetError());
+ }
+ if (tempSurface != EGL_NO_SURFACE)
+ destroyTemporaryOffscreenSurface(tempSurface);
+ if (tempContext != EGL_NO_CONTEXT)
+ eglDestroyContext(m_eglDisplay, tempContext);
+#endif // QT_NO_OPENGL
+}
+
+bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface)
+{
+ Q_ASSERT(surface->surface()->supportsOpenGL());
+
+ eglBindAPI(m_api);
+
+ EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
+
+ // shortcut: on some GPUs, eglMakeCurrent is not a cheap operation
+ if (eglGetCurrentContext() == m_eglContext &&
+ eglGetCurrentDisplay() == m_eglDisplay &&
+ eglGetCurrentSurface(EGL_READ) == eglSurface &&
+ eglGetCurrentSurface(EGL_DRAW) == eglSurface) {
+ return true;
+ }
+
+ const bool ok = eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_eglContext);
+ if (ok) {
+ if (!m_swapIntervalEnvChecked) {
+ m_swapIntervalEnvChecked = true;
+ if (qEnvironmentVariableIsSet("QT_QPA_EGLFS_SWAPINTERVAL")) {
+ QByteArray swapIntervalString = qgetenv("QT_QPA_EGLFS_SWAPINTERVAL");
+ bool intervalOk;
+ const int swapInterval = swapIntervalString.toInt(&intervalOk);
+ if (intervalOk)
+ m_swapIntervalFromEnv = swapInterval;
+ }
+ }
+ const int requestedSwapInterval = m_swapIntervalFromEnv >= 0
+ ? m_swapIntervalFromEnv
+ : surface->format().swapInterval();
+ if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) {
+ m_swapInterval = requestedSwapInterval;
+ if (eglSurface != EGL_NO_SURFACE) // skip if using surfaceless context
+ eglSwapInterval(eglDisplay(), m_swapInterval);
+ }
+ } else {
+ qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError());
+ }
+
+ return ok;
+}
+
+QEGLPlatformContext::~QEGLPlatformContext()
+{
+ if (m_ownsContext && m_eglContext != EGL_NO_CONTEXT)
+ eglDestroyContext(m_eglDisplay, m_eglContext);
+
+ m_eglContext = EGL_NO_CONTEXT;
+}
+
+void QEGLPlatformContext::doneCurrent()
+{
+ eglBindAPI(m_api);
+ bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (!ok)
+ qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError());
+}
+
+void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
+{
+ eglBindAPI(m_api);
+ EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
+ if (eglSurface != EGL_NO_SURFACE) { // skip if using surfaceless context
+ bool ok = eglSwapBuffers(m_eglDisplay, eglSurface);
+ if (!ok)
+ qWarning("QEGLPlatformContext: eglSwapBuffers failed: %x", eglGetError());
+ }
+}
+
+QFunctionPointer QEGLPlatformContext::getProcAddress(const char *procName)
+{
+ eglBindAPI(m_api);
+ QFunctionPointer proc = (QFunctionPointer) eglGetProcAddress(procName);
+#if !defined(Q_OS_WIN) && !defined(Q_OS_INTEGRITY)
+ if (!proc)
+ proc = (QFunctionPointer) dlsym(RTLD_DEFAULT, procName);
+#elif !defined(QT_OPENGL_DYNAMIC)
+ // On systems without KHR_get_all_proc_addresses and without
+ // dynamic linking there still has to be a way to access the
+ // standard GLES functions. QOpenGL(Extra)Functions never makes
+ // direct GL API calls since Qt 5.7, so all such workarounds are
+ // expected to be handled in the platform plugin.
+ if (!proc) {
+ static struct StdFunc {
+ const char *name;
+ QFunctionPointer func;
+ } standardFuncs[] = {
+#if QT_CONFIG(opengles2)
+ { "glBindTexture", (QFunctionPointer) ::glBindTexture },
+ { "glBlendFunc", (QFunctionPointer) ::glBlendFunc },
+ { "glClear", (QFunctionPointer) ::glClear },
+ { "glClearColor", (QFunctionPointer) ::glClearColor },
+ { "glClearStencil", (QFunctionPointer) ::glClearStencil },
+ { "glColorMask", (QFunctionPointer) ::glColorMask },
+ { "glCopyTexImage2D", (QFunctionPointer) ::glCopyTexImage2D },
+ { "glCopyTexSubImage2D", (QFunctionPointer) ::glCopyTexSubImage2D },
+ { "glCullFace", (QFunctionPointer) ::glCullFace },
+ { "glDeleteTextures", (QFunctionPointer) ::glDeleteTextures },
+ { "glDepthFunc", (QFunctionPointer) ::glDepthFunc },
+ { "glDepthMask", (QFunctionPointer) ::glDepthMask },
+ { "glDisable", (QFunctionPointer) ::glDisable },
+ { "glDrawArrays", (QFunctionPointer) ::glDrawArrays },
+ { "glDrawElements", (QFunctionPointer) ::glDrawElements },
+ { "glEnable", (QFunctionPointer) ::glEnable },
+ { "glFinish", (QFunctionPointer) ::glFinish },
+ { "glFlush", (QFunctionPointer) ::glFlush },
+ { "glFrontFace", (QFunctionPointer) ::glFrontFace },
+ { "glGenTextures", (QFunctionPointer) ::glGenTextures },
+ { "glGetBooleanv", (QFunctionPointer) ::glGetBooleanv },
+ { "glGetError", (QFunctionPointer) ::glGetError },
+ { "glGetFloatv", (QFunctionPointer) ::glGetFloatv },
+ { "glGetIntegerv", (QFunctionPointer) ::glGetIntegerv },
+ { "glGetString", (QFunctionPointer) ::glGetString },
+ { "glGetTexParameterfv", (QFunctionPointer) ::glGetTexParameterfv },
+ { "glGetTexParameteriv", (QFunctionPointer) ::glGetTexParameteriv },
+ { "glHint", (QFunctionPointer) ::glHint },
+ { "glIsEnabled", (QFunctionPointer) ::glIsEnabled },
+ { "glIsTexture", (QFunctionPointer) ::glIsTexture },
+ { "glLineWidth", (QFunctionPointer) ::glLineWidth },
+ { "glPixelStorei", (QFunctionPointer) ::glPixelStorei },
+ { "glPolygonOffset", (QFunctionPointer) ::glPolygonOffset },
+ { "glReadPixels", (QFunctionPointer) ::glReadPixels },
+ { "glScissor", (QFunctionPointer) ::glScissor },
+ { "glStencilFunc", (QFunctionPointer) ::glStencilFunc },
+ { "glStencilMask", (QFunctionPointer) ::glStencilMask },
+ { "glStencilOp", (QFunctionPointer) ::glStencilOp },
+ { "glTexImage2D", (QFunctionPointer) ::glTexImage2D },
+ { "glTexParameterf", (QFunctionPointer) ::glTexParameterf },
+ { "glTexParameterfv", (QFunctionPointer) ::glTexParameterfv },
+ { "glTexParameteri", (QFunctionPointer) ::glTexParameteri },
+ { "glTexParameteriv", (QFunctionPointer) ::glTexParameteriv },
+ { "glTexSubImage2D", (QFunctionPointer) ::glTexSubImage2D },
+ { "glViewport", (QFunctionPointer) ::glViewport },
+
+ { "glActiveTexture", (QFunctionPointer) ::glActiveTexture },
+ { "glAttachShader", (QFunctionPointer) ::glAttachShader },
+ { "glBindAttribLocation", (QFunctionPointer) ::glBindAttribLocation },
+ { "glBindBuffer", (QFunctionPointer) ::glBindBuffer },
+ { "glBindFramebuffer", (QFunctionPointer) ::glBindFramebuffer },
+ { "glBindRenderbuffer", (QFunctionPointer) ::glBindRenderbuffer },
+ { "glBlendColor", (QFunctionPointer) ::glBlendColor },
+ { "glBlendEquation", (QFunctionPointer) ::glBlendEquation },
+ { "glBlendEquationSeparate", (QFunctionPointer) ::glBlendEquationSeparate },
+ { "glBlendFuncSeparate", (QFunctionPointer) ::glBlendFuncSeparate },
+ { "glBufferData", (QFunctionPointer) ::glBufferData },
+ { "glBufferSubData", (QFunctionPointer) ::glBufferSubData },
+ { "glCheckFramebufferStatus", (QFunctionPointer) ::glCheckFramebufferStatus },
+ { "glCompileShader", (QFunctionPointer) ::glCompileShader },
+ { "glCompressedTexImage2D", (QFunctionPointer) ::glCompressedTexImage2D },
+ { "glCompressedTexSubImage2D", (QFunctionPointer) ::glCompressedTexSubImage2D },
+ { "glCreateProgram", (QFunctionPointer) ::glCreateProgram },
+ { "glCreateShader", (QFunctionPointer) ::glCreateShader },
+ { "glDeleteBuffers", (QFunctionPointer) ::glDeleteBuffers },
+ { "glDeleteFramebuffers", (QFunctionPointer) ::glDeleteFramebuffers },
+ { "glDeleteProgram", (QFunctionPointer) ::glDeleteProgram },
+ { "glDeleteRenderbuffers", (QFunctionPointer) ::glDeleteRenderbuffers },
+ { "glDeleteShader", (QFunctionPointer) ::glDeleteShader },
+ { "glDetachShader", (QFunctionPointer) ::glDetachShader },
+ { "glDisableVertexAttribArray", (QFunctionPointer) ::glDisableVertexAttribArray },
+ { "glEnableVertexAttribArray", (QFunctionPointer) ::glEnableVertexAttribArray },
+ { "glFramebufferRenderbuffer", (QFunctionPointer) ::glFramebufferRenderbuffer },
+ { "glFramebufferTexture2D", (QFunctionPointer) ::glFramebufferTexture2D },
+ { "glGenBuffers", (QFunctionPointer) ::glGenBuffers },
+ { "glGenerateMipmap", (QFunctionPointer) ::glGenerateMipmap },
+ { "glGenFramebuffers", (QFunctionPointer) ::glGenFramebuffers },
+ { "glGenRenderbuffers", (QFunctionPointer) ::glGenRenderbuffers },
+ { "glGetActiveAttrib", (QFunctionPointer) ::glGetActiveAttrib },
+ { "glGetActiveUniform", (QFunctionPointer) ::glGetActiveUniform },
+ { "glGetAttachedShaders", (QFunctionPointer) ::glGetAttachedShaders },
+ { "glGetAttribLocation", (QFunctionPointer) ::glGetAttribLocation },
+ { "glGetBufferParameteriv", (QFunctionPointer) ::glGetBufferParameteriv },
+ { "glGetFramebufferAttachmentParameteriv", (QFunctionPointer) ::glGetFramebufferAttachmentParameteriv },
+ { "glGetProgramiv", (QFunctionPointer) ::glGetProgramiv },
+ { "glGetProgramInfoLog", (QFunctionPointer) ::glGetProgramInfoLog },
+ { "glGetRenderbufferParameteriv", (QFunctionPointer) ::glGetRenderbufferParameteriv },
+ { "glGetShaderiv", (QFunctionPointer) ::glGetShaderiv },
+ { "glGetShaderInfoLog", (QFunctionPointer) ::glGetShaderInfoLog },
+ { "glGetShaderPrecisionFormat", (QFunctionPointer) ::glGetShaderPrecisionFormat },
+ { "glGetShaderSource", (QFunctionPointer) ::glGetShaderSource },
+ { "glGetUniformfv", (QFunctionPointer) ::glGetUniformfv },
+ { "glGetUniformiv", (QFunctionPointer) ::glGetUniformiv },
+ { "glGetUniformLocation", (QFunctionPointer) ::glGetUniformLocation },
+ { "glGetVertexAttribfv", (QFunctionPointer) ::glGetVertexAttribfv },
+ { "glGetVertexAttribiv", (QFunctionPointer) ::glGetVertexAttribiv },
+ { "glGetVertexAttribPointerv", (QFunctionPointer) ::glGetVertexAttribPointerv },
+ { "glIsBuffer", (QFunctionPointer) ::glIsBuffer },
+ { "glIsFramebuffer", (QFunctionPointer) ::glIsFramebuffer },
+ { "glIsProgram", (QFunctionPointer) ::glIsProgram },
+ { "glIsRenderbuffer", (QFunctionPointer) ::glIsRenderbuffer },
+ { "glIsShader", (QFunctionPointer) ::glIsShader },
+ { "glLinkProgram", (QFunctionPointer) ::glLinkProgram },
+ { "glReleaseShaderCompiler", (QFunctionPointer) ::glReleaseShaderCompiler },
+ { "glRenderbufferStorage", (QFunctionPointer) ::glRenderbufferStorage },
+ { "glSampleCoverage", (QFunctionPointer) ::glSampleCoverage },
+ { "glShaderBinary", (QFunctionPointer) ::glShaderBinary },
+ { "glShaderSource", (QFunctionPointer) ::glShaderSource },
+ { "glStencilFuncSeparate", (QFunctionPointer) ::glStencilFuncSeparate },
+ { "glStencilMaskSeparate", (QFunctionPointer) ::glStencilMaskSeparate },
+ { "glStencilOpSeparate", (QFunctionPointer) ::glStencilOpSeparate },
+ { "glUniform1f", (QFunctionPointer) ::glUniform1f },
+ { "glUniform1fv", (QFunctionPointer) ::glUniform1fv },
+ { "glUniform1i", (QFunctionPointer) ::glUniform1i },
+ { "glUniform1iv", (QFunctionPointer) ::glUniform1iv },
+ { "glUniform2f", (QFunctionPointer) ::glUniform2f },
+ { "glUniform2fv", (QFunctionPointer) ::glUniform2fv },
+ { "glUniform2i", (QFunctionPointer) ::glUniform2i },
+ { "glUniform2iv", (QFunctionPointer) ::glUniform2iv },
+ { "glUniform3f", (QFunctionPointer) ::glUniform3f },
+ { "glUniform3fv", (QFunctionPointer) ::glUniform3fv },
+ { "glUniform3i", (QFunctionPointer) ::glUniform3i },
+ { "glUniform3iv", (QFunctionPointer) ::glUniform3iv },
+ { "glUniform4f", (QFunctionPointer) ::glUniform4f },
+ { "glUniform4fv", (QFunctionPointer) ::glUniform4fv },
+ { "glUniform4i", (QFunctionPointer) ::glUniform4i },
+ { "glUniform4iv", (QFunctionPointer) ::glUniform4iv },
+ { "glUniformMatrix2fv", (QFunctionPointer) ::glUniformMatrix2fv },
+ { "glUniformMatrix3fv", (QFunctionPointer) ::glUniformMatrix3fv },
+ { "glUniformMatrix4fv", (QFunctionPointer) ::glUniformMatrix4fv },
+ { "glUseProgram", (QFunctionPointer) ::glUseProgram },
+ { "glValidateProgram", (QFunctionPointer) ::glValidateProgram },
+ { "glVertexAttrib1f", (QFunctionPointer) ::glVertexAttrib1f },
+ { "glVertexAttrib1fv", (QFunctionPointer) ::glVertexAttrib1fv },
+ { "glVertexAttrib2f", (QFunctionPointer) ::glVertexAttrib2f },
+ { "glVertexAttrib2fv", (QFunctionPointer) ::glVertexAttrib2fv },
+ { "glVertexAttrib3f", (QFunctionPointer) ::glVertexAttrib3f },
+ { "glVertexAttrib3fv", (QFunctionPointer) ::glVertexAttrib3fv },
+ { "glVertexAttrib4f", (QFunctionPointer) ::glVertexAttrib4f },
+ { "glVertexAttrib4fv", (QFunctionPointer) ::glVertexAttrib4fv },
+ { "glVertexAttribPointer", (QFunctionPointer) ::glVertexAttribPointer },
+
+ { "glClearDepthf", (QFunctionPointer) ::glClearDepthf },
+ { "glDepthRangef", (QFunctionPointer) ::glDepthRangef },
+#endif // QT_CONFIG(opengles2)
+
+#if QT_CONFIG(opengles3)
+ { "glBeginQuery", (QFunctionPointer) ::glBeginQuery },
+ { "glBeginTransformFeedback", (QFunctionPointer) ::glBeginTransformFeedback },
+ { "glBindBufferBase", (QFunctionPointer) ::glBindBufferBase },
+ { "glBindBufferRange", (QFunctionPointer) ::glBindBufferRange },
+ { "glBindSampler", (QFunctionPointer) ::glBindSampler },
+ { "glBindTransformFeedback", (QFunctionPointer) ::glBindTransformFeedback },
+ { "glBindVertexArray", (QFunctionPointer) ::glBindVertexArray },
+ { "glBlitFramebuffer", (QFunctionPointer) ::glBlitFramebuffer },
+ { "glClearBufferfi", (QFunctionPointer) ::glClearBufferfi },
+ { "glClearBufferfv", (QFunctionPointer) ::glClearBufferfv },
+ { "glClearBufferiv", (QFunctionPointer) ::glClearBufferiv },
+ { "glClearBufferuiv", (QFunctionPointer) ::glClearBufferuiv },
+ { "glClientWaitSync", (QFunctionPointer) ::glClientWaitSync },
+ { "glCompressedTexImage3D", (QFunctionPointer) ::glCompressedTexImage3D },
+ { "glCompressedTexSubImage3D", (QFunctionPointer) ::glCompressedTexSubImage3D },
+ { "glCopyBufferSubData", (QFunctionPointer) ::glCopyBufferSubData },
+ { "glCopyTexSubImage3D", (QFunctionPointer) ::glCopyTexSubImage3D },
+ { "glDeleteQueries", (QFunctionPointer) ::glDeleteQueries },
+ { "glDeleteSamplers", (QFunctionPointer) ::glDeleteSamplers },
+ { "glDeleteSync", (QFunctionPointer) ::glDeleteSync },
+ { "glDeleteTransformFeedbacks", (QFunctionPointer) ::glDeleteTransformFeedbacks },
+ { "glDeleteVertexArrays", (QFunctionPointer) ::glDeleteVertexArrays },
+ { "glDrawArraysInstanced", (QFunctionPointer) ::glDrawArraysInstanced },
+ { "glDrawBuffers", (QFunctionPointer) ::glDrawBuffers },
+ { "glDrawElementsInstanced", (QFunctionPointer) ::glDrawElementsInstanced },
+ { "glDrawRangeElements", (QFunctionPointer) ::glDrawRangeElements },
+ { "glEndQuery", (QFunctionPointer) ::glEndQuery },
+ { "glEndTransformFeedback", (QFunctionPointer) ::glEndTransformFeedback },
+ { "glFenceSync", (QFunctionPointer) ::glFenceSync },
+ { "glFlushMappedBufferRange", (QFunctionPointer) ::glFlushMappedBufferRange },
+ { "glFramebufferTextureLayer", (QFunctionPointer) ::glFramebufferTextureLayer },
+ { "glGenQueries", (QFunctionPointer) ::glGenQueries },
+ { "glGenSamplers", (QFunctionPointer) ::glGenSamplers },
+ { "glGenTransformFeedbacks", (QFunctionPointer) ::glGenTransformFeedbacks },
+ { "glGenVertexArrays", (QFunctionPointer) ::glGenVertexArrays },
+ { "glGetActiveUniformBlockName", (QFunctionPointer) ::glGetActiveUniformBlockName },
+ { "glGetActiveUniformBlockiv", (QFunctionPointer) ::glGetActiveUniformBlockiv },
+ { "glGetActiveUniformsiv", (QFunctionPointer) ::glGetActiveUniformsiv },
+ { "glGetBufferParameteri64v", (QFunctionPointer) ::glGetBufferParameteri64v },
+ { "glGetBufferPointerv", (QFunctionPointer) ::glGetBufferPointerv },
+ { "glGetFragDataLocation", (QFunctionPointer) ::glGetFragDataLocation },
+ { "glGetInteger64i_v", (QFunctionPointer) ::glGetInteger64i_v },
+ { "glGetInteger64v", (QFunctionPointer) ::glGetInteger64v },
+ { "glGetIntegeri_v", (QFunctionPointer) ::glGetIntegeri_v },
+ { "glGetInternalformativ", (QFunctionPointer) ::glGetInternalformativ },
+ { "glGetProgramBinary", (QFunctionPointer) ::glGetProgramBinary },
+ { "glGetQueryObjectuiv", (QFunctionPointer) ::glGetQueryObjectuiv },
+ { "glGetQueryiv", (QFunctionPointer) ::glGetQueryiv },
+ { "glGetSamplerParameterfv", (QFunctionPointer) ::glGetSamplerParameterfv },
+ { "glGetSamplerParameteriv", (QFunctionPointer) ::glGetSamplerParameteriv },
+ { "glGetStringi", (QFunctionPointer) ::glGetStringi },
+ { "glGetSynciv", (QFunctionPointer) ::glGetSynciv },
+ { "glGetTransformFeedbackVarying", (QFunctionPointer) ::glGetTransformFeedbackVarying },
+ { "glGetUniformBlockIndex", (QFunctionPointer) ::glGetUniformBlockIndex },
+ { "glGetUniformIndices", (QFunctionPointer) ::glGetUniformIndices },
+ { "glGetUniformuiv", (QFunctionPointer) ::glGetUniformuiv },
+ { "glGetVertexAttribIiv", (QFunctionPointer) ::glGetVertexAttribIiv },
+ { "glGetVertexAttribIuiv", (QFunctionPointer) ::glGetVertexAttribIuiv },
+ { "glInvalidateFramebuffer", (QFunctionPointer) ::glInvalidateFramebuffer },
+ { "glInvalidateSubFramebuffer", (QFunctionPointer) ::glInvalidateSubFramebuffer },
+ { "glIsQuery", (QFunctionPointer) ::glIsQuery },
+ { "glIsSampler", (QFunctionPointer) ::glIsSampler },
+ { "glIsSync", (QFunctionPointer) ::glIsSync },
+ { "glIsTransformFeedback", (QFunctionPointer) ::glIsTransformFeedback },
+ { "glIsVertexArray", (QFunctionPointer) ::glIsVertexArray },
+ { "glMapBufferRange", (QFunctionPointer) ::glMapBufferRange },
+ { "glPauseTransformFeedback", (QFunctionPointer) ::glPauseTransformFeedback },
+ { "glProgramBinary", (QFunctionPointer) ::glProgramBinary },
+ { "glProgramParameteri", (QFunctionPointer) ::glProgramParameteri },
+ { "glReadBuffer", (QFunctionPointer) ::glReadBuffer },
+ { "glRenderbufferStorageMultisample", (QFunctionPointer) ::glRenderbufferStorageMultisample },
+ { "glResumeTransformFeedback", (QFunctionPointer) ::glResumeTransformFeedback },
+ { "glSamplerParameterf", (QFunctionPointer) ::glSamplerParameterf },
+ { "glSamplerParameterfv", (QFunctionPointer) ::glSamplerParameterfv },
+ { "glSamplerParameteri", (QFunctionPointer) ::glSamplerParameteri },
+ { "glSamplerParameteriv", (QFunctionPointer) ::glSamplerParameteriv },
+ { "glTexImage3D", (QFunctionPointer) ::glTexImage3D },
+ { "glTexStorage2D", (QFunctionPointer) ::glTexStorage2D },
+ { "glTexStorage3D", (QFunctionPointer) ::glTexStorage3D },
+ { "glTexSubImage3D", (QFunctionPointer) ::glTexSubImage3D },
+ { "glTransformFeedbackVaryings", (QFunctionPointer) ::glTransformFeedbackVaryings },
+ { "glUniform1ui", (QFunctionPointer) ::glUniform1ui },
+ { "glUniform1uiv", (QFunctionPointer) ::glUniform1uiv },
+ { "glUniform2ui", (QFunctionPointer) ::glUniform2ui },
+ { "glUniform2uiv", (QFunctionPointer) ::glUniform2uiv },
+ { "glUniform3ui", (QFunctionPointer) ::glUniform3ui },
+ { "glUniform3uiv", (QFunctionPointer) ::glUniform3uiv },
+ { "glUniform4ui", (QFunctionPointer) ::glUniform4ui },
+ { "glUniform4uiv", (QFunctionPointer) ::glUniform4uiv },
+ { "glUniformBlockBinding", (QFunctionPointer) ::glUniformBlockBinding },
+ { "glUniformMatrix2x3fv", (QFunctionPointer) ::glUniformMatrix2x3fv },
+ { "glUniformMatrix2x4fv", (QFunctionPointer) ::glUniformMatrix2x4fv },
+ { "glUniformMatrix3x2fv", (QFunctionPointer) ::glUniformMatrix3x2fv },
+ { "glUniformMatrix3x4fv", (QFunctionPointer) ::glUniformMatrix3x4fv },
+ { "glUniformMatrix4x2fv", (QFunctionPointer) ::glUniformMatrix4x2fv },
+ { "glUniformMatrix4x3fv", (QFunctionPointer) ::glUniformMatrix4x3fv },
+ { "glUnmapBuffer", (QFunctionPointer) ::glUnmapBuffer },
+ { "glVertexAttribDivisor", (QFunctionPointer) ::glVertexAttribDivisor },
+ { "glVertexAttribI4i", (QFunctionPointer) ::glVertexAttribI4i },
+ { "glVertexAttribI4iv", (QFunctionPointer) ::glVertexAttribI4iv },
+ { "glVertexAttribI4ui", (QFunctionPointer) ::glVertexAttribI4ui },
+ { "glVertexAttribI4uiv", (QFunctionPointer) ::glVertexAttribI4uiv },
+ { "glVertexAttribIPointer", (QFunctionPointer) ::glVertexAttribIPointer },
+ { "glWaitSync", (QFunctionPointer) ::glWaitSync },
+#endif // QT_CONFIG(opengles3)
+
+#if QT_CONFIG(opengles31)
+ { "glActiveShaderProgram", (QFunctionPointer) ::glActiveShaderProgram },
+ { "glBindImageTexture", (QFunctionPointer) ::glBindImageTexture },
+ { "glBindProgramPipeline", (QFunctionPointer) ::glBindProgramPipeline },
+ { "glBindVertexBuffer", (QFunctionPointer) ::glBindVertexBuffer },
+ { "glCreateShaderProgramv", (QFunctionPointer) ::glCreateShaderProgramv },
+ { "glDeleteProgramPipelines", (QFunctionPointer) ::glDeleteProgramPipelines },
+ { "glDispatchCompute", (QFunctionPointer) ::glDispatchCompute },
+ { "glDispatchComputeIndirect", (QFunctionPointer) ::glDispatchComputeIndirect },
+ { "glDrawArraysIndirect", (QFunctionPointer) ::glDrawArraysIndirect },
+ { "glDrawElementsIndirect", (QFunctionPointer) ::glDrawElementsIndirect },
+ { "glFramebufferParameteri", (QFunctionPointer) ::glFramebufferParameteri },
+ { "glGenProgramPipelines", (QFunctionPointer) ::glGenProgramPipelines },
+ { "glGetBooleani_v", (QFunctionPointer) ::glGetBooleani_v },
+ { "glGetFramebufferParameteriv", (QFunctionPointer) ::glGetFramebufferParameteriv },
+ { "glGetMultisamplefv", (QFunctionPointer) ::glGetMultisamplefv },
+ { "glGetProgramInterfaceiv", (QFunctionPointer) ::glGetProgramInterfaceiv },
+ { "glGetProgramPipelineInfoLog", (QFunctionPointer) ::glGetProgramPipelineInfoLog },
+ { "glGetProgramPipelineiv", (QFunctionPointer) ::glGetProgramPipelineiv },
+ { "glGetProgramResourceIndex", (QFunctionPointer) ::glGetProgramResourceIndex },
+ { "glGetProgramResourceLocation", (QFunctionPointer) ::glGetProgramResourceLocation },
+ { "glGetProgramResourceName", (QFunctionPointer) ::glGetProgramResourceName },
+ { "glGetProgramResourceiv", (QFunctionPointer) ::glGetProgramResourceiv },
+ { "glGetTexLevelParameterfv", (QFunctionPointer) ::glGetTexLevelParameterfv },
+ { "glGetTexLevelParameteriv", (QFunctionPointer) ::glGetTexLevelParameteriv },
+ { "glIsProgramPipeline", (QFunctionPointer) ::glIsProgramPipeline },
+ { "glMemoryBarrier", (QFunctionPointer) ::glMemoryBarrier },
+ { "glMemoryBarrierByRegion", (QFunctionPointer) ::glMemoryBarrierByRegion },
+ { "glProgramUniform1f", (QFunctionPointer) ::glProgramUniform1f },
+ { "glProgramUniform1fv", (QFunctionPointer) ::glProgramUniform1fv },
+ { "glProgramUniform1i", (QFunctionPointer) ::glProgramUniform1i },
+ { "glProgramUniform1iv", (QFunctionPointer) ::glProgramUniform1iv },
+ { "glProgramUniform1ui", (QFunctionPointer) ::glProgramUniform1ui },
+ { "glProgramUniform1uiv", (QFunctionPointer) ::glProgramUniform1uiv },
+ { "glProgramUniform2f", (QFunctionPointer) ::glProgramUniform2f },
+ { "glProgramUniform2fv", (QFunctionPointer) ::glProgramUniform2fv },
+ { "glProgramUniform2i", (QFunctionPointer) ::glProgramUniform2i },
+ { "glProgramUniform2iv", (QFunctionPointer) ::glProgramUniform2iv },
+ { "glProgramUniform2ui", (QFunctionPointer) ::glProgramUniform2ui },
+ { "glProgramUniform2uiv", (QFunctionPointer) ::glProgramUniform2uiv },
+ { "glProgramUniform3f", (QFunctionPointer) ::glProgramUniform3f },
+ { "glProgramUniform3fv", (QFunctionPointer) ::glProgramUniform3fv },
+ { "glProgramUniform3i", (QFunctionPointer) ::glProgramUniform3i },
+ { "glProgramUniform3iv", (QFunctionPointer) ::glProgramUniform3iv },
+ { "glProgramUniform3ui", (QFunctionPointer) ::glProgramUniform3ui },
+ { "glProgramUniform3uiv", (QFunctionPointer) ::glProgramUniform3uiv },
+ { "glProgramUniform4f", (QFunctionPointer) ::glProgramUniform4f },
+ { "glProgramUniform4fv", (QFunctionPointer) ::glProgramUniform4fv },
+ { "glProgramUniform4i", (QFunctionPointer) ::glProgramUniform4i },
+ { "glProgramUniform4iv", (QFunctionPointer) ::glProgramUniform4iv },
+ { "glProgramUniform4ui", (QFunctionPointer) ::glProgramUniform4ui },
+ { "glProgramUniform4uiv", (QFunctionPointer) ::glProgramUniform4uiv },
+ { "glProgramUniformMatrix2fv", (QFunctionPointer) ::glProgramUniformMatrix2fv },
+ { "glProgramUniformMatrix2x3fv", (QFunctionPointer) ::glProgramUniformMatrix2x3fv },
+ { "glProgramUniformMatrix2x4fv", (QFunctionPointer) ::glProgramUniformMatrix2x4fv },
+ { "glProgramUniformMatrix3fv", (QFunctionPointer) ::glProgramUniformMatrix3fv },
+ { "glProgramUniformMatrix3x2fv", (QFunctionPointer) ::glProgramUniformMatrix3x2fv },
+ { "glProgramUniformMatrix3x4fv", (QFunctionPointer) ::glProgramUniformMatrix3x4fv },
+ { "glProgramUniformMatrix4fv", (QFunctionPointer) ::glProgramUniformMatrix4fv },
+ { "glProgramUniformMatrix4x2fv", (QFunctionPointer) ::glProgramUniformMatrix4x2fv },
+ { "glProgramUniformMatrix4x3fv", (QFunctionPointer) ::glProgramUniformMatrix4x3fv },
+ { "glSampleMaski", (QFunctionPointer) ::glSampleMaski },
+ { "glTexStorage2DMultisample", (QFunctionPointer) ::glTexStorage2DMultisample },
+ { "glUseProgramStages", (QFunctionPointer) ::glUseProgramStages },
+ { "glValidateProgramPipeline", (QFunctionPointer) ::glValidateProgramPipeline },
+ { "glVertexAttribBinding", (QFunctionPointer) ::glVertexAttribBinding },
+ { "glVertexAttribFormat", (QFunctionPointer) ::glVertexAttribFormat },
+ { "glVertexAttribIFormat", (QFunctionPointer) ::glVertexAttribIFormat },
+ { "glVertexBindingDivisor", (QFunctionPointer) ::glVertexBindingDivisor },
+#endif // QT_CONFIG(opengles31)
+
+#if QT_CONFIG(opengles32)
+ { "glBlendBarrier", (QFunctionPointer) ::glBlendBarrier },
+ { "glCopyImageSubData", (QFunctionPointer) ::glCopyImageSubData },
+ { "glDebugMessageControl", (QFunctionPointer) ::glDebugMessageControl },
+ { "glDebugMessageInsert", (QFunctionPointer) ::glDebugMessageInsert },
+ { "glDebugMessageCallback", (QFunctionPointer) ::glDebugMessageCallback },
+ { "glGetDebugMessageLog", (QFunctionPointer) ::glGetDebugMessageLog },
+ { "glPushDebugGroup", (QFunctionPointer) ::glPushDebugGroup },
+ { "glPopDebugGroup", (QFunctionPointer) ::glPopDebugGroup },
+ { "glObjectLabel", (QFunctionPointer) ::glObjectLabel },
+ { "glGetObjectLabel", (QFunctionPointer) ::glGetObjectLabel },
+ { "glObjectPtrLabel", (QFunctionPointer) ::glObjectPtrLabel },
+ { "glGetObjectPtrLabel", (QFunctionPointer) ::glGetObjectPtrLabel },
+ { "glGetPointerv", (QFunctionPointer) ::glGetPointerv },
+ { "glEnablei", (QFunctionPointer) ::glEnablei },
+ { "glDisablei", (QFunctionPointer) ::glDisablei },
+ { "glBlendEquationi", (QFunctionPointer) ::glBlendEquationi },
+ { "glBlendEquationSeparatei", (QFunctionPointer) ::glBlendEquationSeparatei },
+ { "glBlendFunci", (QFunctionPointer) ::glBlendFunci },
+ { "glBlendFuncSeparatei", (QFunctionPointer) ::glBlendFuncSeparatei },
+ { "glColorMaski", (QFunctionPointer) ::glColorMaski },
+ { "glIsEnabledi", (QFunctionPointer) ::glIsEnabledi },
+ { "glDrawElementsBaseVertex", (QFunctionPointer) ::glDrawElementsBaseVertex },
+ { "glDrawRangeElementsBaseVertex", (QFunctionPointer) ::glDrawRangeElementsBaseVertex },
+ { "glDrawElementsInstancedBaseVertex", (QFunctionPointer) ::glDrawElementsInstancedBaseVertex },
+ { "glFramebufferTexture", (QFunctionPointer) ::glFramebufferTexture },
+ { "glPrimitiveBoundingBox", (QFunctionPointer) ::glPrimitiveBoundingBox },
+ { "glGetGraphicsResetStatus", (QFunctionPointer) ::glGetGraphicsResetStatus },
+ { "glReadnPixels", (QFunctionPointer) ::glReadnPixels },
+ { "glGetnUniformfv", (QFunctionPointer) ::glGetnUniformfv },
+ { "glGetnUniformiv", (QFunctionPointer) ::glGetnUniformiv },
+ { "glGetnUniformuiv", (QFunctionPointer) ::glGetnUniformuiv },
+ { "glMinSampleShading", (QFunctionPointer) ::glMinSampleShading },
+ { "glPatchParameteri", (QFunctionPointer) ::glPatchParameteri },
+ { "glTexParameterIiv", (QFunctionPointer) ::glTexParameterIiv },
+ { "glTexParameterIuiv", (QFunctionPointer) ::glTexParameterIuiv },
+ { "glGetTexParameterIiv", (QFunctionPointer) ::glGetTexParameterIiv },
+ { "glGetTexParameterIuiv", (QFunctionPointer) ::glGetTexParameterIuiv },
+ { "glSamplerParameterIiv", (QFunctionPointer) ::glSamplerParameterIiv },
+ { "glSamplerParameterIuiv", (QFunctionPointer) ::glSamplerParameterIuiv },
+ { "glGetSamplerParameterIiv", (QFunctionPointer) ::glGetSamplerParameterIiv },
+ { "glGetSamplerParameterIuiv", (QFunctionPointer) ::glGetSamplerParameterIuiv },
+ { "glTexBuffer", (QFunctionPointer) ::glTexBuffer },
+ { "glTexBufferRange", (QFunctionPointer) ::glTexBufferRange },
+ { "glTexStorage3DMultisample", (QFunctionPointer) ::glTexStorage3DMultisample },
+#endif // QT_CONFIG(opengles32)
+ };
+
+ for (size_t i = 0; i < sizeof(standardFuncs) / sizeof(StdFunc); ++i) {
+ if (!qstrcmp(procName, standardFuncs[i].name)) {
+ proc = standardFuncs[i].func;
+ break;
+ }
+ }
+ }
+#endif
+
+ return proc;
+}
+
+QSurfaceFormat QEGLPlatformContext::format() const
+{
+ return m_format;
+}
+
+EGLContext QEGLPlatformContext::eglContext() const
+{
+ return m_eglContext;
+}
+
+EGLDisplay QEGLPlatformContext::eglDisplay() const
+{
+ return m_eglDisplay;
+}
+
+EGLConfig QEGLPlatformContext::eglConfig() const
+{
+ return m_eglConfig;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/platform/egl/qeglplatformcontext_p.h b/src/gui/opengl/platform/egl/qeglplatformcontext_p.h
new file mode 100644
index 0000000000..899f4b5c9f
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qeglplatformcontext_p.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLPLATFORMCONTEXT_H
+#define QEGLPLATFORMCONTEXT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qtextstream.h>
+#include <qpa/qplatformwindow.h>
+#include <qpa/qplatformopenglcontext.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/private/qt_egl_p.h>
+#include <QtGui/private/qopenglcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QEGLPlatformContext : public QPlatformOpenGLContext,
+ public QPlatformInterface::QEGLContext
+{
+public:
+ enum Flag {
+ NoSurfaceless = 0x01
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
+ EGLConfig *config = nullptr, Flags flags = { });
+
+ template <typename T>
+ static QOpenGLContext *createFrom(EGLContext context, EGLDisplay contextDisplay,
+ EGLDisplay platformDisplay, QOpenGLContext *shareContext)
+ {
+ if (!context)
+ return nullptr;
+
+ // A context belonging to a given EGLDisplay cannot be used with another one
+ if (contextDisplay != platformDisplay) {
+ qWarning("QEGLPlatformContext: Cannot adopt context from different display");
+ return nullptr;
+ }
+
+ QPlatformOpenGLContext *shareHandle = shareContext ? shareContext->handle() : nullptr;
+
+ auto *resultingContext = new QOpenGLContext;
+ auto *contextPrivate = QOpenGLContextPrivate::get(resultingContext);
+ auto *platformContext = new T;
+ platformContext->adopt(context, contextDisplay, shareHandle);
+ contextPrivate->adopt(platformContext);
+ return resultingContext;
+ }
+
+ ~QEGLPlatformContext();
+
+ void initialize() override;
+ bool makeCurrent(QPlatformSurface *surface) override;
+ void doneCurrent() override;
+ void swapBuffers(QPlatformSurface *surface) override;
+ QFunctionPointer getProcAddress(const char *procName) override;
+
+ QSurfaceFormat format() const override;
+ bool isSharing() const override { return m_shareContext != EGL_NO_CONTEXT; }
+ bool isValid() const override { return m_eglContext != EGL_NO_CONTEXT; }
+
+ EGLContext nativeContext() const override { return eglContext(); }
+
+ EGLContext eglContext() const;
+ EGLDisplay eglDisplay() const;
+ EGLConfig eglConfig() const;
+
+protected:
+ QEGLPlatformContext() {} // For adoption
+ virtual EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) = 0;
+ virtual EGLSurface createTemporaryOffscreenSurface();
+ virtual void destroyTemporaryOffscreenSurface(EGLSurface surface);
+ virtual void runGLChecks();
+
+private:
+ void adopt(EGLContext context, EGLDisplay display, QPlatformOpenGLContext *shareContext);
+ void updateFormatFromGL();
+
+ EGLContext m_eglContext;
+ EGLContext m_shareContext;
+ EGLDisplay m_eglDisplay;
+ EGLConfig m_eglConfig;
+ QSurfaceFormat m_format;
+ EGLenum m_api;
+ int m_swapInterval = -1;
+ bool m_swapIntervalEnvChecked = false;
+ int m_swapIntervalFromEnv = -1;
+ Flags m_flags;
+ bool m_ownsContext = false;
+ QList<EGLint> m_contextAttrs;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QEGLPlatformContext::Flags)
+
+QT_END_NAMESPACE
+
+#endif //QEGLPLATFORMCONTEXT_H
diff --git a/src/gui/opengl/platform/egl/qeglstreamconvenience.cpp b/src/gui/opengl/platform/egl/qeglstreamconvenience.cpp
new file mode 100644
index 0000000000..228cdbb06b
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qeglstreamconvenience.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglstreamconvenience_p.h"
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+QEGLStreamConvenience::QEGLStreamConvenience()
+ : initialized(false),
+ has_egl_platform_device(false),
+ has_egl_device_base(false),
+ has_egl_stream(false),
+ has_egl_stream_producer_eglsurface(false),
+ has_egl_stream_consumer_egloutput(false),
+ has_egl_output_drm(false),
+ has_egl_output_base(false),
+ has_egl_stream_cross_process_fd(false),
+ has_egl_stream_consumer_gltexture(false)
+{
+ const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (!extensions) {
+ qWarning("Failed to query EGL extensions");
+ return;
+ }
+
+ query_devices = reinterpret_cast<PFNEGLQUERYDEVICESEXTPROC>(eglGetProcAddress("eglQueryDevicesEXT"));
+ query_device_string = reinterpret_cast<PFNEGLQUERYDEVICESTRINGEXTPROC>(eglGetProcAddress("eglQueryDeviceStringEXT"));
+ get_platform_display = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
+
+ has_egl_device_base = strstr(extensions, "EGL_EXT_device_base");
+ has_egl_platform_device = strstr(extensions, "EGL_EXT_platform_device");
+}
+
+void QEGLStreamConvenience::initialize(EGLDisplay dpy)
+{
+ if (initialized)
+ return;
+
+ if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+ qWarning("Failed to bind OpenGL ES API");
+ return;
+ }
+
+ const char *extensions = eglQueryString(dpy, EGL_EXTENSIONS);
+ if (!extensions) {
+ qWarning("Failed to query EGL extensions");
+ return;
+ }
+
+ create_stream = reinterpret_cast<PFNEGLCREATESTREAMKHRPROC>(eglGetProcAddress("eglCreateStreamKHR"));
+ destroy_stream = reinterpret_cast<PFNEGLDESTROYSTREAMKHRPROC>(eglGetProcAddress("eglDestroyStreamKHR"));
+ stream_attrib = reinterpret_cast<PFNEGLSTREAMATTRIBKHRPROC>(eglGetProcAddress("eglStreamAttribKHR"));
+ query_stream = reinterpret_cast<PFNEGLQUERYSTREAMKHRPROC>(eglGetProcAddress("eglQueryStreamKHR"));
+ query_stream_u64 = reinterpret_cast<PFNEGLQUERYSTREAMU64KHRPROC>(eglGetProcAddress("eglQueryStreamu64KHR"));
+ create_stream_producer_surface = reinterpret_cast<PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC>(eglGetProcAddress("eglCreateStreamProducerSurfaceKHR"));
+ stream_consumer_output = reinterpret_cast<PFNEGLSTREAMCONSUMEROUTPUTEXTPROC>(eglGetProcAddress("eglStreamConsumerOutputEXT"));
+ get_output_layers = reinterpret_cast<PFNEGLGETOUTPUTLAYERSEXTPROC>(eglGetProcAddress("eglGetOutputLayersEXT"));
+ get_output_ports = reinterpret_cast<PFNEGLGETOUTPUTPORTSEXTPROC>(eglGetProcAddress("eglGetOutputPortsEXT"));
+ output_layer_attrib = reinterpret_cast<PFNEGLOUTPUTLAYERATTRIBEXTPROC>(eglGetProcAddress("eglOutputLayerAttribEXT"));
+ query_output_layer_attrib = reinterpret_cast<PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC>(eglGetProcAddress("eglQueryOutputLayerAttribEXT"));
+ query_output_layer_string = reinterpret_cast<PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC>(eglGetProcAddress("eglQueryOutputLayerStringEXT"));
+ query_output_port_attrib = reinterpret_cast<PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC>(eglGetProcAddress("eglQueryOutputPortAttribEXT"));
+ query_output_port_string = reinterpret_cast<PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC>(eglGetProcAddress("eglQueryOutputPortStringEXT"));
+ get_stream_file_descriptor = reinterpret_cast<PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC>(eglGetProcAddress("eglGetStreamFileDescriptorKHR"));
+ create_stream_from_file_descriptor = reinterpret_cast<PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC>(eglGetProcAddress("eglCreateStreamFromFileDescriptorKHR"));
+ stream_consumer_gltexture = reinterpret_cast<PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC>(eglGetProcAddress("eglStreamConsumerGLTextureExternalKHR"));
+ stream_consumer_acquire = reinterpret_cast<PFNEGLSTREAMCONSUMERACQUIREKHRPROC>(eglGetProcAddress("eglStreamConsumerAcquireKHR"));
+ stream_consumer_release = reinterpret_cast<PFNEGLSTREAMCONSUMERRELEASEKHRPROC>(eglGetProcAddress("eglStreamConsumerReleaseKHR"));
+ create_stream_attrib_nv = reinterpret_cast<PFNEGLCREATESTREAMATTRIBNVPROC>(eglGetProcAddress("eglCreateStreamAttribNV"));
+ set_stream_attrib_nv = reinterpret_cast<PFNEGLSETSTREAMATTRIBNVPROC>(eglGetProcAddress("eglSetStreamAttribNV"));
+ query_stream_attrib_nv = reinterpret_cast<PFNEGLQUERYSTREAMATTRIBNVPROC>(eglGetProcAddress("eglQueryStreamAttribNV"));
+ acquire_stream_attrib_nv = reinterpret_cast<PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC>(eglGetProcAddress("eglStreamConsumerAcquireAttribNV"));
+ release_stream_attrib_nv = reinterpret_cast<PFNEGLSTREAMCONSUMERRELEASEATTRIBNVPROC>(eglGetProcAddress("eglStreamConsumerReleaseAttribNV"));
+
+ has_egl_stream = strstr(extensions, "EGL_KHR_stream");
+ has_egl_stream_producer_eglsurface = strstr(extensions, "EGL_KHR_stream_producer_eglsurface");
+ has_egl_stream_consumer_egloutput = strstr(extensions, "EGL_EXT_stream_consumer_egloutput");
+ has_egl_output_drm = strstr(extensions, "EGL_EXT_output_drm");
+ has_egl_output_base = strstr(extensions, "EGL_EXT_output_base");
+ has_egl_stream_cross_process_fd = strstr(extensions, "EGL_KHR_stream_cross_process_fd");
+ has_egl_stream_consumer_gltexture = strstr(extensions, "EGL_KHR_stream_consumer_gltexture");
+
+ initialized = true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/platform/egl/qeglstreamconvenience_p.h b/src/gui/opengl/platform/egl/qeglstreamconvenience_p.h
new file mode 100644
index 0000000000..22e124b279
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qeglstreamconvenience_p.h
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLSTREAMCONVENIENCE_H
+#define QEGLSTREAMCONVENIENCE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qtguiglobal.h>
+
+#include <QtGui/private/qt_egl_p.h>
+
+// This provides runtime EGLDevice/Output/Stream support even when eglext.h in
+// the sysroot is not up-to-date.
+
+#ifndef EGL_VERSION_1_5
+typedef intptr_t EGLAttrib;
+#endif
+
+#ifndef EGL_EXT_platform_base
+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
+#endif
+
+#ifndef EGL_EXT_device_base
+typedef void *EGLDeviceEXT;
+#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)(0))
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name);
+#endif
+
+#ifndef EGL_EXT_output_base
+typedef void *EGLOutputLayerEXT;
+typedef void *EGLOutputPortEXT;
+#define EGL_NO_OUTPUT_LAYER_EXT ((EGLOutputLayerEXT)0)
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTLAYERSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTPORTSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#endif
+
+#ifndef EGL_KHR_stream
+typedef void *EGLStreamKHR;
+typedef quint64 EGLuint64KHR;
+#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0)
+#define EGL_STREAM_STATE_KHR 0x3214
+#define EGL_STREAM_STATE_CREATED_KHR 0x3215
+#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216
+#define EGL_STREAM_STATE_EMPTY_KHR 0x3217
+#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
+#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
+#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
+#define EGL_BAD_STREAM_KHR 0x321B
+#define EGL_BAD_STATE_KHR 0x321C
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#endif
+
+#ifndef EGL_KHR_stream_fifo
+#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC
+#endif
+
+#ifndef EGL_KHR_stream_producer_eglsurface
+#define EGL_STREAM_BIT_KHR 0x0800
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#endif
+
+#ifndef EGL_KHR_stream_cross_process_fd
+typedef int EGLNativeFileDescriptorKHR;
+#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1))
+typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#endif
+
+#ifndef EGL_KHR_stream_consumer_gltexture
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+#endif
+
+#ifndef EGL_EXT_stream_consumer_egloutput
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#endif
+
+#ifndef EGL_EXT_platform_device
+#define EGL_PLATFORM_DEVICE_EXT 0x313F
+#endif
+
+#ifndef EGL_EXT_device_drm
+#define EGL_DRM_DEVICE_FILE_EXT 0x3233
+#endif
+
+#ifndef EGL_EXT_output_drm
+#define EGL_DRM_CRTC_EXT 0x3234
+#define EGL_DRM_PLANE_EXT 0x3235
+#endif
+
+#ifndef EGL_PLATFORM_X11_KHR
+#define EGL_PLATFORM_X11_KHR 0x31D5
+#endif
+
+#ifndef EGL_NV_stream_attrib
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMATTRIBNVPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QEGLStreamConvenience
+{
+public:
+ QEGLStreamConvenience();
+ void initialize(EGLDisplay dpy);
+
+ PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display;
+ PFNEGLQUERYDEVICESEXTPROC query_devices;
+ PFNEGLQUERYDEVICESTRINGEXTPROC query_device_string;
+ PFNEGLCREATESTREAMKHRPROC create_stream;
+ PFNEGLCREATESTREAMATTRIBNVPROC create_stream_attrib_nv;
+ PFNEGLSETSTREAMATTRIBNVPROC set_stream_attrib_nv;
+ PFNEGLQUERYSTREAMATTRIBNVPROC query_stream_attrib_nv;
+ PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC acquire_stream_attrib_nv;
+ PFNEGLSTREAMCONSUMERRELEASEATTRIBNVPROC release_stream_attrib_nv;
+ PFNEGLDESTROYSTREAMKHRPROC destroy_stream;
+ PFNEGLSTREAMATTRIBKHRPROC stream_attrib;
+ PFNEGLQUERYSTREAMKHRPROC query_stream;
+ PFNEGLQUERYSTREAMU64KHRPROC query_stream_u64;
+ PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC create_stream_producer_surface;
+ PFNEGLSTREAMCONSUMEROUTPUTEXTPROC stream_consumer_output;
+ PFNEGLGETOUTPUTLAYERSEXTPROC get_output_layers;
+ PFNEGLGETOUTPUTPORTSEXTPROC get_output_ports;
+ PFNEGLOUTPUTLAYERATTRIBEXTPROC output_layer_attrib;
+ PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC query_output_layer_attrib;
+ PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC query_output_layer_string;
+ PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC query_output_port_attrib;
+ PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC query_output_port_string;
+ PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC get_stream_file_descriptor;
+ PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC create_stream_from_file_descriptor;
+ PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC stream_consumer_gltexture;
+ PFNEGLSTREAMCONSUMERACQUIREKHRPROC stream_consumer_acquire;
+ PFNEGLSTREAMCONSUMERRELEASEKHRPROC stream_consumer_release;
+
+ bool initialized;
+
+ bool has_egl_platform_device;
+ bool has_egl_device_base;
+ bool has_egl_stream;
+ bool has_egl_stream_producer_eglsurface;
+ bool has_egl_stream_consumer_egloutput;
+ bool has_egl_output_drm;
+ bool has_egl_output_base;
+ bool has_egl_stream_cross_process_fd;
+ bool has_egl_stream_consumer_gltexture;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/opengl/platform/egl/qt_egl_p.h b/src/gui/opengl/platform/egl/qt_egl_p.h
new file mode 100644
index 0000000000..c33cc8aa21
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qt_egl_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_EGL_P_H
+#define QT_EGL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// q(data/text)stream.h must be included before any header file that defines Status
+#include <QtCore/qdatastream.h>
+#include <QtCore/qtextstream.h>
+
+#ifdef QT_EGL_NO_X11
+# ifndef EGL_NO_X11
+# define EGL_NO_X11
+# endif
+# ifndef MESA_EGL_NO_X11_HEADERS
+# define MESA_EGL_NO_X11_HEADERS // MESA
+# endif
+# if !defined(Q_OS_INTEGRITY)
+# define WIN_INTERFACE_CUSTOM // NV
+# endif // Q_OS_INTEGRITY
+#endif // QT_EGL_NO_X11
+
+#ifdef QT_EGL_WAYLAND
+# define WAYLAND // NV
+#endif // QT_EGL_WAYLAND
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <stdint.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtInternal {
+
+template <class FromType, class ToType>
+struct QtEglConverter
+{
+ static inline ToType convert(FromType v)
+ { return v; }
+};
+
+template <>
+struct QtEglConverter<uint32_t, uintptr_t>
+{
+ static inline uintptr_t convert(uint32_t v)
+ { return v; }
+};
+
+#if QT_POINTER_SIZE > 4
+template <>
+struct QtEglConverter<uintptr_t, uint32_t>
+{
+ static inline uint32_t convert(uintptr_t v)
+ { return uint32_t(v); }
+};
+#endif
+
+template <>
+struct QtEglConverter<uint32_t, void *>
+{
+ static inline void *convert(uint32_t v)
+ { return reinterpret_cast<void *>(uintptr_t(v)); }
+};
+
+template <>
+struct QtEglConverter<void *, uint32_t>
+{
+ static inline uint32_t convert(void *v)
+ { return uintptr_t(v); }
+};
+
+} // QtInternal
+
+template <class ToType, class FromType>
+static inline ToType qt_egl_cast(FromType from)
+{ return QtInternal::QtEglConverter<FromType, ToType>::convert(from); }
+
+QT_END_NAMESPACE
+
+#endif // QT_EGL_P_H
diff --git a/src/gui/opengl/platform/egl/qxlibeglintegration.cpp b/src/gui/opengl/platform/egl/qxlibeglintegration.cpp
new file mode 100644
index 0000000000..59f7024c06
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qxlibeglintegration.cpp
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qloggingcategory.h>
+#include "qxlibeglintegration_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcXlibEglDebug, "qt.egl.xlib.debug")
+
+VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config)
+{
+ VisualID visualId = 0;
+ EGLint eglValue = 0;
+
+ EGLint configRedSize = 0;
+ eglGetConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &configRedSize);
+
+ EGLint configGreenSize = 0;
+ eglGetConfigAttrib(eglDisplay, config, EGL_GREEN_SIZE, &configGreenSize);
+
+ EGLint configBlueSize = 0;
+ eglGetConfigAttrib(eglDisplay, config, EGL_BLUE_SIZE, &configBlueSize);
+
+ EGLint configAlphaSize = 0;
+ eglGetConfigAttrib(eglDisplay, config, EGL_ALPHA_SIZE, &configAlphaSize);
+
+ eglGetConfigAttrib(eglDisplay, config, EGL_CONFIG_ID, &eglValue);
+ int configId = eglValue;
+
+ // See if EGL provided a valid VisualID:
+ eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &eglValue);
+ visualId = (VisualID)eglValue;
+ if (visualId) {
+ // EGL has suggested a visual id, so get the rest of the visual info for that id:
+ XVisualInfo visualInfoTemplate;
+ memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
+ visualInfoTemplate.visualid = visualId;
+
+ XVisualInfo *chosenVisualInfo;
+ int matchingCount = 0;
+ chosenVisualInfo = XGetVisualInfo(display, VisualIDMask, &visualInfoTemplate, &matchingCount);
+ if (chosenVisualInfo) {
+ // Skip size checks if implementation supports non-matching visual
+ // and config (QTBUG-9444).
+ if (q_hasEglExtension(eglDisplay,"EGL_NV_post_convert_rounding")) {
+ XFree(chosenVisualInfo);
+ return visualId;
+ }
+ // Skip also for i.MX6 where 565 visuals are suggested for the default 444 configs and it works just fine.
+ const char *vendor = eglQueryString(eglDisplay, EGL_VENDOR);
+ if (vendor && strstr(vendor, "Vivante")) {
+ XFree(chosenVisualInfo);
+ return visualId;
+ }
+
+ int visualRedSize = qPopulationCount(chosenVisualInfo->red_mask);
+ int visualGreenSize = qPopulationCount(chosenVisualInfo->green_mask);
+ int visualBlueSize = qPopulationCount(chosenVisualInfo->blue_mask);
+ int visualAlphaSize = chosenVisualInfo->depth - visualRedSize - visualBlueSize - visualGreenSize;
+
+ const bool visualMatchesConfig = visualRedSize >= configRedSize
+ && visualGreenSize >= configGreenSize
+ && visualBlueSize >= configBlueSize
+ && visualAlphaSize >= configAlphaSize;
+
+ // In some cases EGL tends to suggest a 24-bit visual for 8888
+ // configs. In such a case we have to fall back to XGetVisualInfo.
+ if (!visualMatchesConfig) {
+ visualId = 0;
+ qCDebug(lcXlibEglDebug,
+ "EGL suggested using X Visual ID %d (%d %d %d %d depth %d) for EGL config %d"
+ "(%d %d %d %d), but this is incompatible",
+ (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, visualAlphaSize, chosenVisualInfo->depth,
+ configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize);
+ }
+ } else {
+ qCDebug(lcXlibEglDebug, "EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
+ (int)visualId, configId);
+ visualId = 0;
+ }
+ XFree(chosenVisualInfo);
+ }
+ else
+ qCDebug(lcXlibEglDebug, "EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
+
+ if (visualId) {
+ qCDebug(lcXlibEglDebug, configAlphaSize > 0
+ ? "Using ARGB Visual ID %d provided by EGL for config %d"
+ : "Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId);
+ return visualId;
+ }
+
+ // Finally, try to use XGetVisualInfo and only use the bit depths to match on:
+ if (!visualId) {
+ XVisualInfo visualInfoTemplate;
+ memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
+ XVisualInfo *matchingVisuals;
+ int matchingCount = 0;
+
+ visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
+ matchingVisuals = XGetVisualInfo(display,
+ VisualDepthMask,
+ &visualInfoTemplate,
+ &matchingCount);
+ if (!matchingVisuals) {
+ // Try again without taking the alpha channel into account:
+ visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize;
+ matchingVisuals = XGetVisualInfo(display,
+ VisualDepthMask,
+ &visualInfoTemplate,
+ &matchingCount);
+ }
+
+ if (matchingVisuals) {
+ visualId = matchingVisuals[0].visualid;
+ XFree(matchingVisuals);
+ }
+ }
+
+ if (visualId) {
+ qCDebug(lcXlibEglDebug, "Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId);
+ return visualId;
+ }
+
+ qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
+ return (VisualID)0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/platform/egl/qxlibeglintegration_p.h b/src/gui/opengl/platform/egl/qxlibeglintegration_p.h
new file mode 100644
index 0000000000..2c4e0b5080
--- /dev/null
+++ b/src/gui/opengl/platform/egl/qxlibeglintegration_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXLIBEGLINTEGRATION_H
+#define QXLIBEGLINTEGRATION_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qeglconvenience_p.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QXlibEglIntegration
+{
+public:
+ static VisualID getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config);
+};
+
+QT_END_NAMESPACE
+
+#endif // QXLIBEGLINTEGRATION_H
diff --git a/src/gui/opengl/platform/platform.pri b/src/gui/opengl/platform/platform.pri
index 4255f09a4e..193bd9e59b 100644
--- a/src/gui/opengl/platform/platform.pri
+++ b/src/gui/opengl/platform/platform.pri
@@ -1,2 +1,4 @@
qtConfig(xlib):qtConfig(opengl):!qtConfig(opengles2): \
include(unix/unix.pri)
+qtConfig(egl): \
+ include(egl/egl.pri)