diff options
Diffstat (limited to 'src/platformsupport/eglconvenience')
18 files changed, 2304 insertions, 64 deletions
diff --git a/src/platformsupport/eglconvenience/eglconvenience.pri b/src/platformsupport/eglconvenience/eglconvenience.pri index 506f4ab4ea..c026ff5a4b 100644 --- a/src/platformsupport/eglconvenience/eglconvenience.pri +++ b/src/platformsupport/eglconvenience/eglconvenience.pri @@ -3,11 +3,33 @@ contains(QT_CONFIG,egl) { $$PWD/qeglconvenience_p.h \ $$PWD/qeglplatformcontext_p.h \ $$PWD/qeglpbuffer_p.h + SOURCES += \ $$PWD/qeglconvenience.cpp \ $$PWD/qeglplatformcontext.cpp \ $$PWD/qeglpbuffer.cpp + unix { + HEADERS += \ + $$PWD/qeglplatformcursor_p.h \ + $$PWD/qeglplatformwindow_p.h \ + $$PWD/qeglplatformscreen_p.h \ + $$PWD/qeglcompositor_p.h \ + $$PWD/qeglplatformbackingstore_p.h \ + $$PWD/qeglplatformintegration_p.h + + SOURCES += \ + $$PWD/qeglplatformcursor.cpp \ + $$PWD/qeglplatformwindow.cpp \ + $$PWD/qeglplatformscreen.cpp \ + $$PWD/qeglcompositor.cpp \ + $$PWD/qeglplatformbackingstore.cpp \ + $$PWD/qeglplatformintegration.cpp + } + + # Avoid X11 header collision + DEFINES += MESA_EGL_NO_X11_HEADERS + contains(QT_CONFIG,xlib) { HEADERS += \ $$PWD/qxlibeglintegration_p.h @@ -15,5 +37,15 @@ contains(QT_CONFIG,egl) { $$PWD/qxlibeglintegration.cpp } CONFIG += egl -} +} else: contains(QT_CONFIG,dynamicgl) { + HEADERS += \ + $$PWD/qeglconvenience_p.h \ + $$PWD/qeglplatformcontext_p.h \ + $$PWD/qeglpbuffer_p.h + + SOURCES += \ + $$PWD/qeglconvenience.cpp \ + $$PWD/qeglplatformcontext.cpp \ + $$PWD/qeglpbuffer.cpp +} diff --git a/src/platformsupport/eglconvenience/qeglcompositor.cpp b/src/platformsupport/eglconvenience/qeglcompositor.cpp new file mode 100644 index 0000000000..0e0a2d9375 --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglcompositor.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/QOpenGLContext> +#include <QtGui/QOpenGLShaderProgram> +#include <QtGui/QOpenGLFramebufferObject> +#include <QtGui/private/qopengltextureblitter_p.h> +#include <qpa/qplatformbackingstore.h> + +#include "qeglcompositor_p.h" +#include "qeglplatformwindow_p.h" +#include "qeglplatformscreen_p.h" + +QT_BEGIN_NAMESPACE + +static QEGLCompositor *compositor = 0; + +QEGLCompositor::QEGLCompositor() + : m_context(0), + m_window(0), + m_blitter(0) +{ + Q_ASSERT(!compositor); + m_updateTimer.setSingleShot(true); + m_updateTimer.setInterval(0); + connect(&m_updateTimer, SIGNAL(timeout()), SLOT(renderAll())); +} + +QEGLCompositor::~QEGLCompositor() +{ + Q_ASSERT(compositor == this); + if (m_blitter) { + m_blitter->destroy(); + delete m_blitter; + } + compositor = 0; +} + +void QEGLCompositor::schedule(QOpenGLContext *context, QEGLPlatformWindow *window) +{ + m_context = context; + m_window = window; + if (!m_updateTimer.isActive()) + m_updateTimer.start(); +} + +void QEGLCompositor::renderAll() +{ + Q_ASSERT(m_context && m_window); + m_context->makeCurrent(m_window->window()); + + if (!m_blitter) { + m_blitter = new QOpenGLTextureBlitter; + m_blitter->create(); + } + m_blitter->bind(); + + QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); + QList<QEGLPlatformWindow *> windows = screen->windows(); + for (int i = 0; i < windows.size(); ++i) + render(windows.at(i)); + + m_blitter->release(); + m_context->swapBuffers(m_window->window()); + + for (int i = 0; i < windows.size(); ++i) + windows.at(i)->composited(); +} + +void QEGLCompositor::render(QEGLPlatformWindow *window) +{ + const QPlatformTextureList *textures = window->textures(); + if (!textures) + return; + + const QRect targetWindowRect(QPoint(0, 0), window->screen()->geometry().size()); + glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height()); + + for (int i = 0; i < textures->count(); ++i) { + uint textureId = textures->textureId(i); + glBindTexture(GL_TEXTURE_2D, textureId); + QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), + targetWindowRect); + + if (textures->count() > 1 && i == textures->count() - 1) { + // Backingstore for a widget with QOpenGLWidget subwidgets + m_blitter->setSwizzleRB(true); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); + glDisable(GL_BLEND); + } else if (textures->count() == 1) { + // A regular QWidget window + m_blitter->setSwizzleRB(true); + m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); + } else { + // Texture from an FBO belonging to a QOpenGLWidget + m_blitter->setSwizzleRB(false); + m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft); + } + } +} + +QEGLCompositor *QEGLCompositor::instance() +{ + if (!compositor) + compositor = new QEGLCompositor; + return compositor; +} + +void QEGLCompositor::destroy() +{ + delete compositor; + compositor = 0; +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglcompositor_p.h b/src/platformsupport/eglconvenience/qeglcompositor_p.h new file mode 100644 index 0000000000..370345ada6 --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglcompositor_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLCOMPOSITOR_H +#define QEGLCOMPOSITOR_H + +#include <QtCore/QTimer> + +QT_BEGIN_NAMESPACE + +class QOpenGLContext; +class QOpenGLTextureBlitter; +class QEGLPlatformWindow; + +class QEGLCompositor : public QObject +{ + Q_OBJECT + +public: + void schedule(QOpenGLContext *context, QEGLPlatformWindow *window); + + static QEGLCompositor *instance(); + static void destroy(); + +private slots: + void renderAll(); + +private: + QEGLCompositor(); + ~QEGLCompositor(); + + void render(QEGLPlatformWindow *window); + + QOpenGLContext *m_context; + QEGLPlatformWindow *m_window; + QTimer m_updateTimer; + QOpenGLTextureBlitter *m_blitter; +}; + +QT_END_NAMESPACE + +#endif // QEGLCOMPOSITOR_H diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp index 32f553a3f5..7cf1f88b02 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience.cpp +++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp @@ -40,9 +40,20 @@ ****************************************************************************/ #include <QByteArray> +#include <QOpenGLContext> + +#ifdef Q_OS_LINUX +#include <sys/ioctl.h> +#include <linux/fb.h> +#include <private/qmath_p.h> +#endif #include "qeglconvenience_p.h" +#ifndef EGL_OPENGL_ES3_BIT_KHR +#define EGL_OPENGL_ES3_BIT_KHR 0x0040 +#endif + QT_BEGIN_NAMESPACE QVector<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format) @@ -232,17 +243,23 @@ EGLConfig QEglConfigChooser::chooseConfig() 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 -# if !defined(QT_OPENGL_ES_2) case QSurfaceFormat::DefaultRenderableType: -# endif - case QSurfaceFormat::OpenGL: - configureAttributes.append(EGL_OPENGL_BIT); +#ifndef QT_NO_OPENGL + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::DesktopGL) + 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) { @@ -251,9 +268,15 @@ EGLConfig QEglConfigChooser::chooseConfig() } // fall through default: - configureAttributes.append(EGL_OPENGL_ES2_BIT); + 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 = 0; @@ -347,11 +370,14 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, if (referenceFormat.renderableType() == QSurfaceFormat::OpenVG && (renderableType & EGL_OPENVG_BIT)) format.setRenderableType(QSurfaceFormat::OpenVG); #ifdef EGL_VERSION_1_4 - else if ((referenceFormat.renderableType() == QSurfaceFormat::OpenGL -# if !defined(QT_OPENGL_ES_2) - || referenceFormat.renderableType() == QSurfaceFormat::DefaultRenderableType -# endif - ) && (renderableType & EGL_OPENGL_BIT)) + 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::DesktopGL +#endif + && (renderableType & EGL_OPENGL_BIT)) format.setRenderableType(QSurfaceFormat::OpenGL); #endif else @@ -365,6 +391,7 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, 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 @@ -426,4 +453,108 @@ void q_printEglConfig(EGLDisplay display, EGLConfig config) qWarning("\n"); } +#ifdef Q_OS_LINUX + +QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize) +{ + const int defaultPhysicalDpi = 100; + static QSizeF size; + + if (size.isEmpty()) { + // Note: in millimeters + int width = qgetenv("QT_QPA_EGLFS_PHYSICAL_WIDTH").toInt(); + int height = qgetenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT").toInt(); + + if (width && height) { + size.setWidth(width); + size.setHeight(height); + return size; + } + + struct fb_var_screeninfo vinfo; + int w = -1; + int h = -1; + QSize screenResolution; + + 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 { + // 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)); + } + + return size; +} + +QSize q_screenSizeFromFb(int framebufferDevice) +{ + const int defaultWidth = 800; + const int defaultHeight = 600; + static QSize size; + + if (size.isEmpty()) { + int width = qgetenv("QT_QPA_EGLFS_WIDTH").toInt(); + int height = qgetenv("QT_QPA_EGLFS_HEIGHT").toInt(); + + if (width && height) { + size.setWidth(width); + size.setHeight(height); + return size; + } + + 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); + } + + return size; +} + +int q_screenDepthFromFb(int framebufferDevice) +{ + const int defaultDepth = 32; + static int depth = qgetenv("QT_QPA_EGLFS_DEPTH").toInt(); + + if (depth == 0) { + 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; + } + + return depth; +} + +#endif // Q_OS_LINUX + QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglconvenience_p.h b/src/platformsupport/eglconvenience/qeglconvenience_p.h index 35c225cc2f..8616275e53 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience_p.h +++ b/src/platformsupport/eglconvenience/qeglconvenience_p.h @@ -42,11 +42,11 @@ #ifndef QEGLCONVENIENCE_H #define QEGLCONVENIENCE_H - #include <QtGui/QSurfaceFormat> #include <QtCore/QVector> - +#include <QtCore/QSizeF> #include <EGL/egl.h> + QT_BEGIN_NAMESPACE QVector<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format); @@ -56,6 +56,12 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config, bool q_hasEglExtension(EGLDisplay display,const char* extensionName); void q_printEglConfig(EGLDisplay display, EGLConfig config); +#ifdef Q_OS_UNIX +QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize = QSize()); +QSize q_screenSizeFromFb(int framebufferDevice); +int q_screenDepthFromFb(int framebufferDevice); +#endif + class QEglConfigChooser { public: diff --git a/src/platformsupport/eglconvenience/qeglpbuffer.cpp b/src/platformsupport/eglconvenience/qeglpbuffer.cpp index 919314e9aa..295f8756c4 100644 --- a/src/platformsupport/eglconvenience/qeglpbuffer.cpp +++ b/src/platformsupport/eglconvenience/qeglpbuffer.cpp @@ -45,6 +45,18 @@ 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) : QPlatformOffscreenSurface(offscreenSurface) , m_format(format) diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp new file mode 100644 index 0000000000..24e9ccd39f --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/QOpenGLShaderProgram> +#include <QtGui/QOpenGLContext> + +#include "qeglplatformbackingstore_p.h" +#include "qeglcompositor_p.h" +#include "qeglplatformwindow_p.h" +#include "qeglplatformscreen_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QEGLPlatformBackingStore + \brief A backing store implementation for EGL and GLES. + \since 5.2 + \internal + \ingroup qpa + + This implementation uploads raster-rendered widget windows into + textures and composites them onto a single native window using + QEGLCompositor. This means that multiple top-level widgets are + supported without creating actual native windows for each of them. + + The class is ready to be used as-is, the default + QEGLPlatformIntegration::createPlatformBackingStore() + implementation creates an instance which is ready to be used + without further customization. + + If QEGLCompositor is not suitable, this backing store + implementation can also be used without it. In this case a + subclass must reimplement composite() and schedule an update in + its custom compositor when this function is called. The textures + are accessible via QEGLPlatformWindow::texture(). +*/ + +QEGLPlatformBackingStore::QEGLPlatformBackingStore(QWindow *window) + : QPlatformBackingStore(window), + m_window(static_cast<QEGLPlatformWindow *>(window->handle())), + m_bsTexture(0), + m_textures(new QPlatformTextureList), + m_lockedWidgetTextures(0) +{ + m_window->setBackingStore(this); +} + +QEGLPlatformBackingStore::~QEGLPlatformBackingStore() +{ + delete m_textures; +} + +QPaintDevice *QEGLPlatformBackingStore::paintDevice() +{ + return &m_image; +} + +void QEGLPlatformBackingStore::updateTexture() +{ + if (!m_bsTexture) { + glGenTextures(1, &m_bsTexture); + glBindTexture(GL_TEXTURE_2D, m_bsTexture); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + // QOpenGLTextureBlitter requires GL_REPEAT for the time being + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + } else { + glBindTexture(GL_TEXTURE_2D, m_bsTexture); + } + + if (!m_dirty.isNull()) { + QRegion fixed; + QRect imageRect = m_image.rect(); + + foreach (const QRect &rect, m_dirty.rects()) { + // intersect with image rect to be sure + QRect r = imageRect & rect; + + // if the rect is wide enough it's cheaper to just + // extend it instead of doing an image copy + if (r.width() >= imageRect.width() / 2) { + r.setX(0); + r.setWidth(imageRect.width()); + } + + fixed |= r; + } + + foreach (const QRect &rect, fixed.rects()) { + // if the sub-rect is full-width we can pass the image data directly to + // OpenGL instead of copying, since there's no gap between scanlines + if (rect.width() == imageRect.width()) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + m_image.constScanLine(rect.y())); + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + m_image.copy(rect).constBits()); + } + } + + m_dirty = QRegion(); + } +} + +void QEGLPlatformBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) +{ + // Called for ordinary raster windows. This is rare since RasterGLSurface + // support is claimed which leads to having all QWidget windows marked as + // RasterGLSurface instead of just Raster. These go through + // compositeAndFlush() instead of this function. + + Q_UNUSED(region); + Q_UNUSED(offset); + + QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); + QEGLPlatformWindow *dstWin = screen->compositingWindow(); + if (!dstWin || !dstWin->isRaster()) + return; + + screen->compositingContext()->makeCurrent(dstWin->window()); + updateTexture(); + m_textures->clear(); + m_textures->appendTexture(m_bsTexture, window->geometry()); + composite(screen->compositingContext(), dstWin); +} + +void QEGLPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, + QPlatformTextureList *textures, QOpenGLContext *context) +{ + // QOpenGLWidget content provided as textures. The raster content should go on top. + + Q_UNUSED(region); + Q_UNUSED(offset); + Q_UNUSED(context); + + QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); + QEGLPlatformWindow *dstWin = screen->compositingWindow(); + if (!dstWin || !dstWin->isRaster()) + return; + + screen->compositingContext()->makeCurrent(dstWin->window()); + + m_textures->clear(); + for (int i = 0; i < textures->count(); ++i) { + uint textureId = textures->textureId(i); + QRect geom = textures->geometry(i); + m_textures->appendTexture(textureId, geom); + } + + updateTexture(); + m_textures->appendTexture(m_bsTexture, window->geometry()); + + textures->lock(true); + m_lockedWidgetTextures = textures; + + composite(screen->compositingContext(), dstWin); +} + +void QEGLPlatformBackingStore::composite(QOpenGLContext *context, QEGLPlatformWindow *window) +{ + QEGLCompositor::instance()->schedule(context, window); +} + +void QEGLPlatformBackingStore::composited() +{ + if (m_lockedWidgetTextures) { + QPlatformTextureList *textureList = m_lockedWidgetTextures; + m_lockedWidgetTextures = 0; // may reenter so null before unlocking + textureList->lock(false); + } +} + +void QEGLPlatformBackingStore::beginPaint(const QRegion &rgn) +{ + m_dirty |= rgn; +} + +void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents) +{ + Q_UNUSED(staticContents); + + QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); + QEGLPlatformWindow *dstWin = screen->compositingWindow(); + if (!dstWin || (!dstWin->isRaster() && dstWin->window()->surfaceType() != QSurface::RasterGLSurface)) + return; + + m_image = QImage(size, QImage::Format_RGB32); + m_window->create(); + + screen->compositingContext()->makeCurrent(dstWin->window()); + if (m_bsTexture) { + glDeleteTextures(1, &m_bsTexture); + m_bsTexture = 0; + } +} + +QImage QEGLPlatformBackingStore::toImage() const +{ + return m_image; +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h b/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h new file mode 100644 index 0000000000..cb1e5999b0 --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglplatformbackingstore_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLPLATFORMBACKINGSTORE_H +#define QEGLPLATFORMBACKINGSTORE_H + +#include <qpa/qplatformbackingstore.h> + +#include <QImage> +#include <QRegion> + +QT_BEGIN_NAMESPACE + +class QOpenGLContext; +class QPlatformTextureList; +class QEGLPlatformWindow; + +class QEGLPlatformBackingStore : public QPlatformBackingStore +{ +public: + QEGLPlatformBackingStore(QWindow *window); + ~QEGLPlatformBackingStore(); + + QPaintDevice *paintDevice() Q_DECL_OVERRIDE; + + void beginPaint(const QRegion &) Q_DECL_OVERRIDE; + + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; + void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; + + QImage toImage() const Q_DECL_OVERRIDE; + void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, + QPlatformTextureList *textures, QOpenGLContext *context) Q_DECL_OVERRIDE; + + const QPlatformTextureList *textures() const { return m_textures; } + + virtual void composite(QOpenGLContext *context, QEGLPlatformWindow *window); + + void composited(); + +private: + void updateTexture(); + + QEGLPlatformWindow *m_window; + QImage m_image; + QRegion m_dirty; + uint m_bsTexture; + QPlatformTextureList *m_textures; + QPlatformTextureList *m_lockedWidgetTextures; +}; + +QT_END_NAMESPACE + +#endif // QEGLPLATFORMBACKINGSTORE_H diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 716b01b4d9..9c3b9b539c 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -40,78 +40,216 @@ ****************************************************************************/ #include "qeglplatformcontext_p.h" - #include "qeglconvenience_p.h" - +#include "qeglpbuffer_p.h" #include <qpa/qplatformwindow.h> +#include <QOpenGLContext> -#include <EGL/egl.h> +QT_BEGIN_NAMESPACE -static inline void bindApi(const QSurfaceFormat &format) -{ - switch (format.renderableType()) { - case QSurfaceFormat::OpenVG: - eglBindAPI(EGL_OPENVG_API); - break; -#ifdef EGL_VERSION_1_4 -# if !defined(QT_OPENGL_ES_2) - case QSurfaceFormat::DefaultRenderableType: -# endif - case QSurfaceFormat::OpenGL: - eglBindAPI(EGL_OPENGL_API); - break; +/*! + \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 - case QSurfaceFormat::OpenGLES: - default: - eglBindAPI(EGL_OPENGL_ES_API); - break; - } -} -QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLenum eglApi) +// 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) : m_eglDisplay(display) , m_eglConfig(q_configFromGLFormat(display, format)) + , m_swapInterval(-1) + , m_swapIntervalEnvChecked(false) + , m_swapIntervalFromEnv(-1) { init(format, share); - Q_UNUSED(eglApi); } QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig config, EGLenum eglApi) + EGLConfig config) : m_eglDisplay(display) , m_eglConfig(config) + , m_swapInterval(-1) + , m_swapIntervalEnvChecked(false) + , m_swapIntervalFromEnv(-1) { init(format, share); - Q_UNUSED(eglApi); } void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share) { m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig); + // 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 : 0; QVector<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); + } + } contextAttrs.append(EGL_NONE); - bindApi(m_format); + 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 = 0; m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, 0, contextAttrs.constData()); } + + if (m_eglContext == EGL_NO_CONTEXT) { + qWarning("QEGLPlatformContext::init: eglError: %x, this: %p \n", eglGetError(), this); + return; + } + +#ifndef QT_NO_OPENGL + // 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 + }; + EGLSurface pbuffer = eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, pbufferAttributes); + if (pbuffer == EGL_NO_SURFACE) + return; + + if (eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) { + 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); + } + } + } + } + eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + } + eglDestroySurface(m_eglDisplay, pbuffer); +#endif // QT_NO_OPENGL } bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) { - Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface); + Q_ASSERT(surface->surface()->supportsOpenGL()); -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::makeCurrent: %p\n",this); -#endif - bindApi(m_format); + eglBindAPI(m_api); EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface); @@ -145,14 +283,32 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) } #endif + + if (ok) { + if (!m_swapIntervalEnvChecked) { + m_swapIntervalEnvChecked = true; + if (qEnvironmentVariableIsSet("QT_QPA_EGLFS_SWAPINTERVAL")) { + QByteArray swapIntervalString = qgetenv("QT_QPA_EGLFS_SWAPINTERVAL"); + bool ok; + const int swapInterval = swapIntervalString.toInt(&ok); + if (ok) + m_swapIntervalFromEnv = swapInterval; + } + } + const int requestedSwapInterval = m_swapIntervalFromEnv >= 0 + ? m_swapIntervalFromEnv + : surface->format().swapInterval(); + if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) { + m_swapInterval = requestedSwapInterval; + eglSwapInterval(eglDisplay(), m_swapInterval); + } + } + return ok; } QEGLPlatformContext::~QEGLPlatformContext() { -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::~QEglContext(): %p\n",this); -#endif if (m_eglContext != EGL_NO_CONTEXT) { eglDestroyContext(m_eglDisplay, m_eglContext); m_eglContext = EGL_NO_CONTEXT; @@ -161,10 +317,7 @@ QEGLPlatformContext::~QEGLPlatformContext() void QEGLPlatformContext::doneCurrent() { -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::doneCurrent:%p\n",this); -#endif - bindApi(m_format); + eglBindAPI(m_api); bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!ok) qWarning("QEGLPlatformContext::doneCurrent(): eglError: %d, this: %p \n", eglGetError(), this); @@ -172,10 +325,7 @@ void QEGLPlatformContext::doneCurrent() void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface) { -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::swapBuffers:%p\n",this); -#endif - bindApi(m_format); + eglBindAPI(m_api); EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface); bool ok = eglSwapBuffers(m_eglDisplay, eglSurface); if (!ok) @@ -184,10 +334,7 @@ void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface) void (*QEGLPlatformContext::getProcAddress(const QByteArray &procName)) () { -#ifdef QEGL_EXTRA_DEBUG - qWarning("QEglContext::getProcAddress%p\n",this); -#endif - bindApi(m_format); + eglBindAPI(m_api); return eglGetProcAddress(procName.constData()); } @@ -210,3 +357,5 @@ EGLConfig QEGLPlatformContext::eglConfig() const { return m_eglConfig; } + +QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index 7c05894246..714633c3bc 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -46,13 +46,14 @@ #include <qpa/qplatformopenglcontext.h> #include <EGL/egl.h> +QT_BEGIN_NAMESPACE + class QEGLPlatformContext : public QPlatformOpenGLContext { public: + QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display); QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLenum eglApi = EGL_OPENGL_ES_API); - QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, - EGLConfig config, EGLenum eglApi = EGL_OPENGL_ES_API); + EGLConfig config); ~QEGLPlatformContext(); bool makeCurrent(QPlatformSurface *surface); @@ -79,6 +80,12 @@ private: EGLDisplay m_eglDisplay; EGLConfig m_eglConfig; QSurfaceFormat m_format; + EGLenum m_api; + int m_swapInterval; + bool m_swapIntervalEnvChecked; + int m_swapIntervalFromEnv; }; +QT_END_NAMESPACE + #endif //QEGLPLATFORMCONTEXT_H diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp new file mode 100644 index 0000000000..70e7c4e4db --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp @@ -0,0 +1,391 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qpa/qwindowsysteminterface.h> +#include <QtGui/QOpenGLContext> +#include <QtGui/QOpenGLShaderProgram> +#include <QtCore/QJsonDocument> +#include <QtCore/QJsonArray> +#include <QtCore/QJsonObject> +#include <QtDebug> + +#include <QtPlatformSupport/private/qdevicediscovery_p.h> + +#include "qeglplatformcursor_p.h" +#include "qeglplatformintegration_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QEGLPlatformCursor + \brief Mouse cursor implementation using OpenGL. + \since 5.2 + \internal + \ingroup qpa + */ + +QEGLPlatformCursor::QEGLPlatformCursor(QPlatformScreen *screen) + : m_visible(true), + m_screen(screen), + m_program(0), + m_vertexCoordEntry(0), + m_textureCoordEntry(0), + m_textureEntry(0), + m_deviceListener(0) +{ + QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR"); + if (!hideCursorVal.isEmpty()) + m_visible = hideCursorVal.toInt() == 0; + if (!m_visible) + return; + + // Try to load the cursor atlas. If this fails, m_visible is set to false and + // paintOnScreen() and setCurrentCursor() become no-ops. + initCursorAtlas(); + + // initialize the cursor +#ifndef QT_NO_CURSOR + QCursor cursor(Qt::ArrowCursor); + setCurrentCursor(&cursor); +#endif +} + +QEGLPlatformCursor::~QEGLPlatformCursor() +{ + resetResources(); + delete m_deviceListener; +} + +void QEGLPlatformCursor::setMouseDeviceDiscovery(QDeviceDiscovery *dd) +{ + if (m_visible && dd) { + m_deviceListener = new QEGLPlatformCursorDeviceListener(dd, this); + updateMouseStatus(); + } +} + +void QEGLPlatformCursor::updateMouseStatus() +{ + m_visible = m_deviceListener->hasMouse(); +} + +QEGLPlatformCursorDeviceListener::QEGLPlatformCursorDeviceListener(QDeviceDiscovery *dd, QEGLPlatformCursor *cursor) + : m_cursor(cursor) +{ + m_mouseCount = dd->scanConnectedDevices().count(); + connect(dd, SIGNAL(deviceDetected(QString)), SLOT(onDeviceAdded())); + connect(dd, SIGNAL(deviceRemoved(QString)), SLOT(onDeviceRemoved())); +} + +bool QEGLPlatformCursorDeviceListener::hasMouse() const +{ + return m_mouseCount > 0; +} + +void QEGLPlatformCursorDeviceListener::onDeviceAdded() +{ + ++m_mouseCount; + m_cursor->updateMouseStatus(); +} + +void QEGLPlatformCursorDeviceListener::onDeviceRemoved() +{ + --m_mouseCount; + m_cursor->updateMouseStatus(); +} + +void QEGLPlatformCursor::resetResources() +{ + if (QOpenGLContext::currentContext()) { + delete m_program; + glDeleteTextures(1, &m_cursor.customCursorTexture); + glDeleteTextures(1, &m_cursorAtlas.texture); + } + m_program = 0; + m_cursor.customCursorTexture = 0; + m_cursor.customCursorPending = !m_cursor.customCursorImage.isNull(); + m_cursorAtlas.texture = 0; +} + +void QEGLPlatformCursor::createShaderPrograms() +{ + static const char *textureVertexProgram = + "attribute highp vec2 vertexCoordEntry;\n" + "attribute highp vec2 textureCoordEntry;\n" + "varying highp vec2 textureCoord;\n" + "void main() {\n" + " textureCoord = textureCoordEntry;\n" + " gl_Position = vec4(vertexCoordEntry, 1.0, 1.0);\n" + "}\n"; + + static const char *textureFragmentProgram = + "uniform sampler2D texture;\n" + "varying highp vec2 textureCoord;\n" + "void main() {\n" + " gl_FragColor = texture2D(texture, textureCoord).bgra;\n" + "}\n"; + + m_program = new QOpenGLShaderProgram; + m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); + m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); + m_program->link(); + + m_vertexCoordEntry = m_program->attributeLocation("vertexCoordEntry"); + m_textureCoordEntry = m_program->attributeLocation("textureCoordEntry"); + m_textureEntry = m_program->attributeLocation("texture"); +} + +void QEGLPlatformCursor::createCursorTexture(uint *texture, const QImage &image) +{ + if (!*texture) + glGenTextures(1, texture); + glBindTexture(GL_TEXTURE_2D, *texture); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, image.width(), image.height(), 0 /* border */, + GL_RGBA, GL_UNSIGNED_BYTE, image.constBits()); +} + +void QEGLPlatformCursor::initCursorAtlas() +{ + static QByteArray json = qgetenv("QT_QPA_EGLFS_CURSOR"); + if (json.isEmpty()) + json = ":/cursor.json"; + + QFile file(QString::fromUtf8(json)); + if (!file.open(QFile::ReadOnly)) { + m_visible = false; + return; + } + + QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + QJsonObject object = doc.object(); + + QString atlas = object.value(QLatin1String("image")).toString(); + Q_ASSERT(!atlas.isEmpty()); + + const int cursorsPerRow = object.value(QLatin1String("cursorsPerRow")).toDouble(); + Q_ASSERT(cursorsPerRow); + m_cursorAtlas.cursorsPerRow = cursorsPerRow; + + const QJsonArray hotSpots = object.value(QLatin1String("hotSpots")).toArray(); + Q_ASSERT(hotSpots.count() == Qt::LastCursor + 1); + for (int i = 0; i < hotSpots.count(); i++) { + QPoint hotSpot(hotSpots[i].toArray()[0].toDouble(), hotSpots[i].toArray()[1].toDouble()); + m_cursorAtlas.hotSpots << hotSpot; + } + + QImage image = QImage(atlas).convertToFormat(QImage::Format_ARGB32_Premultiplied); + m_cursorAtlas.cursorWidth = image.width() / m_cursorAtlas.cursorsPerRow; + m_cursorAtlas.cursorHeight = image.height() / ((Qt::LastCursor + cursorsPerRow) / cursorsPerRow); + m_cursorAtlas.width = image.width(); + m_cursorAtlas.height = image.height(); + m_cursorAtlas.image = image; +} + +#ifndef QT_NO_CURSOR +void QEGLPlatformCursor::changeCursor(QCursor *cursor, QWindow *window) +{ + Q_UNUSED(window); + const QRect oldCursorRect = cursorRect(); + if (setCurrentCursor(cursor)) + update(oldCursorRect | cursorRect()); +} + +bool QEGLPlatformCursor::setCurrentCursor(QCursor *cursor) +{ + if (!m_visible) + return false; + + const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor; + if (m_cursor.shape == newShape && newShape != Qt::BitmapCursor) + return false; + + if (m_cursor.shape == Qt::BitmapCursor) { + m_cursor.customCursorImage = QImage(); + m_cursor.customCursorPending = false; + } + m_cursor.shape = newShape; + if (newShape != Qt::BitmapCursor) { // standard cursor + const float ws = (float)m_cursorAtlas.cursorWidth / m_cursorAtlas.width, + hs = (float)m_cursorAtlas.cursorHeight / m_cursorAtlas.height; + m_cursor.textureRect = QRectF(ws * (m_cursor.shape % m_cursorAtlas.cursorsPerRow), + hs * (m_cursor.shape / m_cursorAtlas.cursorsPerRow), + ws, hs); + m_cursor.hotSpot = m_cursorAtlas.hotSpots[m_cursor.shape]; + m_cursor.texture = m_cursorAtlas.texture; + m_cursor.size = QSize(m_cursorAtlas.cursorWidth, m_cursorAtlas.cursorHeight); + } else { + QImage image = cursor->pixmap().toImage(); + m_cursor.textureRect = QRectF(0, 0, 1, 1); + m_cursor.hotSpot = cursor->hotSpot(); + m_cursor.texture = 0; // will get updated in the next render() + m_cursor.size = image.size(); + m_cursor.customCursorImage = image; + m_cursor.customCursorPending = true; + } + + return true; +} +#endif + +void QEGLPlatformCursor::update(const QRegion &rgn) +{ + QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(m_cursor.pos), rgn); + QWindowSystemInterface::flushWindowSystemEvents(); +} + +QRect QEGLPlatformCursor::cursorRect() const +{ + return QRect(m_cursor.pos - m_cursor.hotSpot, m_cursor.size); +} + +QPoint QEGLPlatformCursor::pos() const +{ + return m_cursor.pos; +} + +void QEGLPlatformCursor::setPos(const QPoint &pos) +{ + const QRect oldCursorRect = cursorRect(); + m_cursor.pos = pos; + update(oldCursorRect | cursorRect()); +} + +void QEGLPlatformCursor::pointerEvent(const QMouseEvent &event) +{ + if (event.type() != QEvent::MouseMove) + return; + const QRect oldCursorRect = cursorRect(); + m_cursor.pos = event.screenPos().toPoint(); + update(oldCursorRect | cursorRect()); +} + +void QEGLPlatformCursor::paintOnScreen() +{ + if (!m_visible) + return; + + const QRectF cr = cursorRect(); + const QRect screenRect(m_screen->geometry()); + const GLfloat x1 = 2 * (cr.left() / screenRect.width()) - 1; + const GLfloat x2 = 2 * (cr.right() / screenRect.width()) - 1; + const GLfloat y1 = 1 - (cr.top() / screenRect.height()) * 2; + const GLfloat y2 = 1 - (cr.bottom() / screenRect.height()) * 2; + QRectF r(QPointF(x1, y1), QPointF(x2, y2)); + + draw(r); +} + +void QEGLPlatformCursor::draw(const QRectF &r) +{ + if (!m_program) { + // one time initialization + createShaderPrograms(); + + if (!m_cursorAtlas.texture) { + createCursorTexture(&m_cursorAtlas.texture, m_cursorAtlas.image); + + if (m_cursor.shape != Qt::BitmapCursor) + m_cursor.texture = m_cursorAtlas.texture; + } + } + + if (m_cursor.shape == Qt::BitmapCursor && m_cursor.customCursorPending) { + // upload the custom cursor + createCursorTexture(&m_cursor.customCursorTexture, m_cursor.customCursorImage); + m_cursor.texture = m_cursor.customCursorTexture; + m_cursor.customCursorPending = false; + } + + Q_ASSERT(m_cursor.texture); + + m_program->bind(); + + const GLfloat x1 = r.left(); + const GLfloat x2 = r.right(); + const GLfloat y1 = r.top(); + const GLfloat y2 = r.bottom(); + const GLfloat cursorCoordinates[] = { + x1, y2, + x2, y2, + x1, y1, + x2, y1 + }; + + const GLfloat s1 = m_cursor.textureRect.left(); + const GLfloat s2 = m_cursor.textureRect.right(); + const GLfloat t1 = m_cursor.textureRect.top(); + const GLfloat t2 = m_cursor.textureRect.bottom(); + const GLfloat textureCoordinates[] = { + s1, t2, + s2, t2, + s1, t1, + s2, t1 + }; + + glBindTexture(GL_TEXTURE_2D, m_cursor.texture); + + m_program->enableAttributeArray(m_vertexCoordEntry); + m_program->enableAttributeArray(m_textureCoordEntry); + + m_program->setAttributeArray(m_vertexCoordEntry, cursorCoordinates, 2); + m_program->setAttributeArray(m_textureCoordEntry, textureCoordinates, 2); + + m_program->setUniformValue(m_textureEntry, 0); + + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); // disable depth testing to make sure cursor is always on top + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDisable(GL_BLEND); + + glBindTexture(GL_TEXTURE_2D, 0); + m_program->disableAttributeArray(m_textureCoordEntry); + m_program->disableAttributeArray(m_vertexCoordEntry); + + m_program->release(); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h new file mode 100644 index 0000000000..c9ff9a1198 --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLPLATFORMCURSOR_H +#define QEGLPLATFORMCURSOR_H + +#include <qpa/qplatformcursor.h> +#include <qpa/qplatformscreen.h> + +QT_BEGIN_NAMESPACE + +class QOpenGLShaderProgram; +class QDeviceDiscovery; +class QEGLPlatformCursor; + +class QEGLPlatformCursorDeviceListener : public QObject +{ + Q_OBJECT + +public: + QEGLPlatformCursorDeviceListener(QDeviceDiscovery *dd, QEGLPlatformCursor *cursor); + bool hasMouse() const; + +private slots: + void onDeviceAdded(); + void onDeviceRemoved(); + +private: + QEGLPlatformCursor *m_cursor; + int m_mouseCount; +}; + +class QEGLPlatformCursor : public QPlatformCursor +{ +public: + QEGLPlatformCursor(QPlatformScreen *screen); + ~QEGLPlatformCursor(); + +#ifndef QT_NO_CURSOR + void changeCursor(QCursor *cursor, QWindow *widget) Q_DECL_OVERRIDE; +#endif + void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE; + QPoint pos() const Q_DECL_OVERRIDE; + void setPos(const QPoint &pos) Q_DECL_OVERRIDE; + + QRect cursorRect() const; + void paintOnScreen(); + void resetResources(); + + void setMouseDeviceDiscovery(QDeviceDiscovery *dd); + void updateMouseStatus(); + +private: +#ifndef QT_NO_CURSOR + bool setCurrentCursor(QCursor *cursor); +#endif + void draw(const QRectF &rect); + void update(const QRegion ®ion); + void createShaderPrograms(); + static void createCursorTexture(uint *texture, const QImage &image); + void initCursorAtlas(); + + // current cursor information + struct Cursor { + Cursor() : texture(0), shape(Qt::BlankCursor), customCursorTexture(0), customCursorPending(false) { } + uint texture; // a texture from 'image' or the atlas + Qt::CursorShape shape; + QRectF textureRect; // normalized rect inside texture + QSize size; // size of the cursor + QPoint hotSpot; + QImage customCursorImage; + QPoint pos; // current cursor position + uint customCursorTexture; + bool customCursorPending; + } m_cursor; + + // cursor atlas information + struct CursorAtlas { + CursorAtlas() : cursorsPerRow(0), texture(0), cursorWidth(0), cursorHeight(0) { } + int cursorsPerRow; + uint texture; + int width, height; // width and height of the atlas + int cursorWidth, cursorHeight; // width and height of cursors inside the atlas + QList<QPoint> hotSpots; + QImage image; // valid until it's uploaded + } m_cursorAtlas; + + bool m_visible; + QPlatformScreen *m_screen; + QOpenGLShaderProgram *m_program; + int m_vertexCoordEntry; + int m_textureCoordEntry; + int m_textureEntry; + QEGLPlatformCursorDeviceListener *m_deviceListener; +}; + +QT_END_NAMESPACE + +#endif // QEGLPLATFORMCURSOR_H diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp new file mode 100644 index 0000000000..b48f993436 --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp @@ -0,0 +1,296 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/QWindow> +#include <QtGui/QOpenGLContext> +#include <QtGui/QOffscreenSurface> +#include <QtGui/QGuiApplication> +#include <qpa/qwindowsysteminterface.h> +#include <qpa/qplatforminputcontextfactory_p.h> + +#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h> +#include <QtPlatformSupport/private/qgenericunixservices_p.h> +#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h> +#include <QtPlatformSupport/private/qfbvthandler_p.h> + +#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) +#include <QtPlatformSupport/private/qevdevmousemanager_p.h> +#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h> +#include <QtPlatformSupport/private/qevdevtouch_p.h> +#endif + +#include "qeglplatformintegration_p.h" +#include "qeglplatformcontext_p.h" +#include "qeglplatformwindow_p.h" +#include "qeglplatformbackingstore_p.h" +#include "qeglplatformscreen_p.h" +#include "qeglplatformcursor_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QEGLPlatformIntegration + \brief Base class for EGL-based QPlatformIntegration implementations. + \since 5.2 + \internal + \ingroup qpa + + This class provides most of the necessary platform integration for + an EGL-based Unix system. Platform plugins must subclass this and + reimplement the virtuals for creating platform screens and windows + since they will most likely wish to use a subclass for these. + + The backing store, native interface accessors, font database, + basic capability flags, etc. are provided out of the box, no + further customization is needed. + + \note It is critical that this class' implementation of + initialize() is called. Therefore subclasses should either avoid + to reimplement this function or call the base class + implementation. + */ + +QEGLPlatformIntegration::QEGLPlatformIntegration() + : m_screen(0), + m_display(EGL_NO_DISPLAY), + m_inputContext(0), + m_fontDb(new QGenericUnixFontDatabase), + m_services(new QGenericUnixServices) +{ +} + +QEGLPlatformIntegration::~QEGLPlatformIntegration() +{ + delete m_screen; + if (m_display != EGL_NO_DISPLAY) + eglTerminate(m_display); +} + +void QEGLPlatformIntegration::initialize() +{ + m_display = eglGetDisplay(nativeDisplay()); + if (m_display == EGL_NO_DISPLAY) + qFatal("Could not open egl display"); + + EGLint major, minor; + if (!eglInitialize(m_display, &major, &minor)) + qFatal("Could not initialize egl display"); + + m_screen = createScreen(); + screenAdded(m_screen); + + m_inputContext = QPlatformInputContextFactory::create(); + + m_vtHandler.reset(new QFbVtHandler); +} + +QAbstractEventDispatcher *QEGLPlatformIntegration::createEventDispatcher() const +{ + return createUnixEventDispatcher(); +} + +QPlatformServices *QEGLPlatformIntegration::services() const +{ + return m_services.data(); +} + +QPlatformFontDatabase *QEGLPlatformIntegration::fontDatabase() const +{ + return m_fontDb.data(); +} + +QPlatformBackingStore *QEGLPlatformIntegration::createPlatformBackingStore(QWindow *window) const +{ + return new QEGLPlatformBackingStore(window); +} + +QPlatformWindow *QEGLPlatformIntegration::createPlatformWindow(QWindow *window) const +{ + QWindowSystemInterface::flushWindowSystemEvents(); + QEGLPlatformWindow *w = createWindow(window); + w->create(); + if (window->type() != Qt::ToolTip) + w->requestActivateWindow(); + return w; +} + +QPlatformOpenGLContext *QEGLPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const +{ + QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(context->screen()->handle()); + // If there is a "root" window into which raster and QOpenGLWidget content is + // composited, all other contexts must share with its context. + QOpenGLContext *compositingContext = screen ? screen->compositingContext() : 0; + return createContext(context->format(), + compositingContext ? compositingContext->handle() : context->shareHandle(), + display()); +} + +QPlatformOffscreenSurface *QEGLPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(surface->screen()->handle()); + return createOffscreenSurface(screen->display(), surface->requestedFormat(), surface); +} + +bool QEGLPlatformIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + case OpenGL: return true; + case ThreadedOpenGL: return true; + case WindowManagement: return false; + case RasterGLSurface: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + +QPlatformNativeInterface *QEGLPlatformIntegration::nativeInterface() const +{ + return const_cast<QEGLPlatformIntegration *>(this); +} + +enum ResourceType { + EglDisplay, + EglWindow, + EglContext +}; + +static int resourceType(const QByteArray &key) +{ + static const QByteArray names[] = { // match ResourceType + QByteArrayLiteral("egldisplay"), + QByteArrayLiteral("eglwindow"), + QByteArrayLiteral("eglcontext") + }; + const QByteArray *end = names + sizeof(names) / sizeof(names[0]); + const QByteArray *result = std::find(names, end, key); + if (result == end) + result = std::find(names, end, key.toLower()); + return int(result - names); +} + +void *QEGLPlatformIntegration::nativeResourceForIntegration(const QByteArray &resource) +{ + void *result = 0; + + switch (resourceType(resource)) { + case EglDisplay: + result = m_screen->display(); + break; + default: + break; + } + + return result; +} + +void *QEGLPlatformIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window) +{ + void *result = 0; + + switch (resourceType(resource)) { + case EglDisplay: + if (window && window->handle()) + result = static_cast<QEGLPlatformScreen *>(window->handle()->screen())->display(); + else + result = m_screen->display(); + break; + case EglWindow: + if (window && window->handle()) + result = reinterpret_cast<void*>(static_cast<QEGLPlatformWindow *>(window->handle())->eglWindow()); + break; + default: + break; + } + + return result; +} + +void *QEGLPlatformIntegration::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) +{ + void *result = 0; + + switch (resourceType(resource)) { + case EglContext: + if (context->handle()) + result = static_cast<QEGLPlatformContext *>(context->handle())->eglContext(); + break; + default: + break; + } + + return result; +} + +static void *eglContextForContext(QOpenGLContext *context) +{ + Q_ASSERT(context); + + QEGLPlatformContext *handle = static_cast<QEGLPlatformContext *>(context->handle()); + if (!handle) + return 0; + + return handle->eglContext(); +} + +QPlatformNativeInterface::NativeResourceForContextFunction QEGLPlatformIntegration::nativeResourceFunctionForContext(const QByteArray &resource) +{ + QByteArray lowerCaseResource = resource.toLower(); + if (lowerCaseResource == "get_egl_context") + return NativeResourceForContextFunction(eglContextForContext); + + return 0; +} + +void QEGLPlatformIntegration::createInputHandlers() +{ +#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) + new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this); + QEvdevMouseManager *mouseMgr = new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this); + Q_FOREACH (QScreen *screen, QGuiApplication::screens()) { + QEGLPlatformCursor *cursor = static_cast<QEGLPlatformCursor *>(screen->handle()->cursor()); + if (cursor) + cursor->setMouseDeviceDiscovery(mouseMgr->deviceDiscovery()); + } + new QEvdevTouchScreenHandlerThread(QString() /* spec */, this); +#endif +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h new file mode 100644 index 0000000000..f665455383 --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLPLATFORMINTEGRATION_H +#define QEGLPLATFORMINTEGRATION_H + +#include <qpa/qplatformintegration.h> +#include <qpa/qplatformnativeinterface.h> +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +class QEGLPlatformScreen; +class QEGLPlatformWindow; +class QEGLPlatformContext; +class QFbVtHandler; + +class QEGLPlatformIntegration : public QPlatformIntegration, public QPlatformNativeInterface +{ +public: + QEGLPlatformIntegration(); + ~QEGLPlatformIntegration(); + + void initialize() Q_DECL_OVERRIDE; + + QEGLPlatformScreen *screen() const { return m_screen; } + EGLDisplay display() const { return m_display; } + + QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; + QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; + QPlatformServices *services() const Q_DECL_OVERRIDE; + QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE { return m_inputContext; } + + QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; + + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; + + QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE; + // QPlatformNativeInterface + void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE; + void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) Q_DECL_OVERRIDE; + void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) Q_DECL_OVERRIDE; + NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE; + +protected: + virtual QEGLPlatformScreen *createScreen() const = 0; + virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0; + virtual QEGLPlatformContext *createContext(const QSurfaceFormat &format, + QPlatformOpenGLContext *shareContext, + EGLDisplay display) const = 0; + virtual QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display, + const QSurfaceFormat &format, + QOffscreenSurface *surface) const = 0; + + virtual EGLNativeDisplayType nativeDisplay() const { return EGL_DEFAULT_DISPLAY; } + + void createInputHandlers(); + +private: + QEGLPlatformScreen *m_screen; + EGLDisplay m_display; + QPlatformInputContext *m_inputContext; + QScopedPointer<QPlatformFontDatabase> m_fontDb; + QScopedPointer<QPlatformServices> m_services; + QScopedPointer<QFbVtHandler> m_vtHandler; +}; + +QT_END_NAMESPACE + +#endif // QEGLPLATFORMINTEGRATION_H diff --git a/src/platformsupport/eglconvenience/qeglplatformscreen.cpp b/src/platformsupport/eglconvenience/qeglplatformscreen.cpp new file mode 100644 index 0000000000..72e7f6a6df --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglplatformscreen.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglcompositor_p.h" +#include "qeglplatformscreen_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QEGLPlatformScreen + \brief Base class for EGL-based platform screen implementations. + \since 5.2 + \internal + \ingroup qpa + + This class provides a lightweight base for QPlatformScreen + implementations. It covers basic window stack management which is + necessary when compositing multiple raster (widget-based) windows + together into one single native surface. + + Reimplementing the virtuals are essential when using + QEGLPlatformBackingStore. The context and the window returned from + these are the ones that are used when compositing the textures + generated from the raster (widget) based windows. + + \note It is up to the QEGLPlatformWindow subclasses to use the + functions, like addWindow(), removeWindow(), etc., provided here. + */ + +QEGLPlatformScreen::QEGLPlatformScreen(EGLDisplay dpy) + : m_dpy(dpy) +{ +} + +QEGLPlatformScreen::~QEGLPlatformScreen() +{ + QEGLCompositor::destroy(); +} + +void QEGLPlatformScreen::addWindow(QEGLPlatformWindow *window) +{ + if (!m_windows.contains(window)) { + m_windows.append(window); + topWindowChanged(window); + } +} + +void QEGLPlatformScreen::removeWindow(QEGLPlatformWindow *window) +{ + m_windows.removeOne(window); + if (!m_windows.isEmpty()) + topWindowChanged(m_windows.last()); +} + +void QEGLPlatformScreen::moveToTop(QEGLPlatformWindow *window) +{ + m_windows.removeOne(window); + m_windows.append(window); + topWindowChanged(window); +} + +void QEGLPlatformScreen::changeWindowIndex(QEGLPlatformWindow *window, int newIdx) +{ + int idx = m_windows.indexOf(window); + if (idx != -1 && idx != newIdx) { + m_windows.move(idx, newIdx); + if (newIdx == m_windows.size() - 1) + topWindowChanged(m_windows.last()); + } +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformscreen_p.h b/src/platformsupport/eglconvenience/qeglplatformscreen_p.h new file mode 100644 index 0000000000..d0d8a52a87 --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglplatformscreen_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLPLATFORMSCREEN_H +#define QEGLPLATFORMSCREEN_H + +#include <QtCore/QList> +#include <qpa/qplatformscreen.h> +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +class QOpenGLContext; +class QEGLPlatformWindow; + +class QEGLPlatformScreen : public QPlatformScreen +{ +public: + QEGLPlatformScreen(EGLDisplay dpy); + ~QEGLPlatformScreen(); + + QList<QEGLPlatformWindow *> windows() const { return m_windows; } + + void addWindow(QEGLPlatformWindow *window); + void removeWindow(QEGLPlatformWindow *window); + void moveToTop(QEGLPlatformWindow *window); + void changeWindowIndex(QEGLPlatformWindow *window, int newIdx); + + virtual void topWindowChanged(QEGLPlatformWindow *window) { Q_UNUSED(window); } + + EGLDisplay display() const { return m_dpy; } + + virtual QEGLPlatformWindow *compositingWindow() = 0; + virtual QOpenGLContext *compositingContext() = 0; + +private: + QList<QEGLPlatformWindow *> m_windows; + EGLDisplay m_dpy; +}; + +QT_END_NAMESPACE + +#endif // QEGLPLATFORMSCREEN_H diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow.cpp b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp new file mode 100644 index 0000000000..e9b79512ba --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglplatformwindow.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qpa/qwindowsysteminterface.h> + +#include "qeglplatformwindow_p.h" +#include "qeglplatformbackingstore_p.h" +#include "qeglplatformscreen_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QEGLPlatformWindow + \brief Base class for EGL-based platform window implementations. + \since 5.2 + \internal + \ingroup qpa + + Lightweight class providing some basic platform window operations + and interfacing with QEGLPlatformBackingStore. + + Almost no QPlatformWindow functions are implemented here. This is + intentional because different platform plugins may use different + strategies for their window management (some may force fullscreen + windows, some may not, some may share the underlying native + surface, some may not, etc.) and therefore it is not sensible to + enforce anything for these functions. + + \note Subclasses are responsible for invoking this class' + implementation of create(). When using QEGLPlatformScreen, the + subclasses of this class are expected to utilize the window stack + management functions (addWindow() etc.) provided there. + */ + +QEGLPlatformWindow::QEGLPlatformWindow(QWindow *w) + : QPlatformWindow(w), + m_winId(0) +{ +} + +static WId newWId() +{ + static WId id = 0; + + if (id == std::numeric_limits<WId>::max()) + qWarning("QEGLPlatformWindow: Out of window IDs"); + + return ++id; +} + +void QEGLPlatformWindow::create() +{ + m_winId = newWId(); + + // Save the original surface type before changing to OpenGLSurface. + m_raster = (window()->surfaceType() == QSurface::RasterSurface); + if (m_raster) // change to OpenGL, but not for RasterGLSurface + window()->setSurfaceType(QSurface::OpenGLSurface); + + if (window()->type() == Qt::Desktop) { + QRect fullscreenRect(QPoint(), screen()->availableGeometry().size()); + QPlatformWindow::setGeometry(fullscreenRect); + QWindowSystemInterface::handleGeometryChange(window(), fullscreenRect); + return; + } +} + +bool QEGLPlatformWindow::isRaster() const +{ + return m_raster || window()->surfaceType() == QSurface::RasterGLSurface; +} + +const QPlatformTextureList *QEGLPlatformWindow::textures() const +{ + if (m_backingStore) + return m_backingStore->textures(); + + return 0; +} + +void QEGLPlatformWindow::composited() +{ + if (m_backingStore) + m_backingStore->composited(); +} + +WId QEGLPlatformWindow::winId() const +{ + return m_winId; +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformwindow_p.h b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h new file mode 100644 index 0000000000..17a1d07a79 --- /dev/null +++ b/src/platformsupport/eglconvenience/qeglplatformwindow_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLPLATFORMWINDOW_H +#define QEGLPLATFORMWINDOW_H + +#include <qpa/qplatformwindow.h> +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +class QEGLPlatformBackingStore; +class QPlatformTextureList; + +class QEGLPlatformWindow : public QPlatformWindow +{ +public: + QEGLPlatformWindow(QWindow *w); + + virtual void create(); + + QEGLPlatformBackingStore *backingStore() { return m_backingStore; } + void setBackingStore(QEGLPlatformBackingStore *backingStore) { m_backingStore = backingStore; } + const QPlatformTextureList *textures() const; + void composited(); + bool isRaster() const; + + WId winId() const Q_DECL_OVERRIDE; + + virtual EGLNativeWindowType eglWindow() const = 0; + +private: + QEGLPlatformBackingStore *m_backingStore; + bool m_raster; + WId m_winId; +}; + +QT_END_NAMESPACE + +#endif // QEGLPLATFORMWINDOW_H |