From 80cd06fd9d26aa7df02f71e001b449d65bb5b7a3 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 8 Oct 2013 14:55:28 +0200 Subject: eglfs: Separate compositor and improve raster window support Separating the compositor into a separate source file improves the chances of possible future reuse and paves the way to supporting multiple GL windows. Tooltips are now working too. Implemented a few window functions like raise() and lower(). Fixed the qFatal for multiple GL windows to be raised in non-SDK based Android builds too. Change-Id: Id94d2fb2a4382766f3d130eebe1e6f397a535852 Reviewed-by: Gunnar Sletta --- src/plugins/platforms/eglfs/eglfs.pri | 6 +- src/plugins/platforms/eglfs/qeglfsbackingstore.cpp | 177 ++---------------- src/plugins/platforms/eglfs/qeglfsbackingstore.h | 35 +--- src/plugins/platforms/eglfs/qeglfscompositor.cpp | 198 +++++++++++++++++++++ src/plugins/platforms/eglfs/qeglfscompositor.h | 83 +++++++++ src/plugins/platforms/eglfs/qeglfsintegration.cpp | 27 +-- src/plugins/platforms/eglfs/qeglfsscreen.cpp | 22 ++- src/plugins/platforms/eglfs/qeglfsscreen.h | 7 +- src/plugins/platforms/eglfs/qeglfswindow.cpp | 87 ++++++--- src/plugins/platforms/eglfs/qeglfswindow.h | 11 +- 10 files changed, 412 insertions(+), 241 deletions(-) create mode 100644 src/plugins/platforms/eglfs/qeglfscompositor.cpp create mode 100644 src/plugins/platforms/eglfs/qeglfscompositor.h (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/eglfs.pri b/src/plugins/platforms/eglfs/eglfs.pri index 4c066d6f26..390061c168 100644 --- a/src/plugins/platforms/eglfs/eglfs.pri +++ b/src/plugins/platforms/eglfs/eglfs.pri @@ -16,7 +16,8 @@ SOURCES += $$PWD/qeglfsintegration.cpp \ $$PWD/qeglfsscreen.cpp \ $$PWD/qeglfshooks_stub.cpp \ $$PWD/qeglfscursor.cpp \ - $$PWD/qeglfscontext.cpp + $$PWD/qeglfscontext.cpp \ + $$PWD/qeglfscompositor.cpp HEADERS += $$PWD/qeglfsintegration.h \ $$PWD/qeglfswindow.h \ @@ -24,7 +25,8 @@ HEADERS += $$PWD/qeglfsintegration.h \ $$PWD/qeglfsscreen.h \ $$PWD/qeglfscursor.h \ $$PWD/qeglfshooks.h \ - $$PWD/qeglfscontext.h + $$PWD/qeglfscontext.h \ + $$PWD/qeglfscompositor.h QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp index ec2f4f9d91..8de8268616 100644 --- a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp +++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp @@ -40,120 +40,24 @@ ****************************************************************************/ #include "qeglfsbackingstore.h" +#include "qeglfscompositor.h" #include "qeglfscursor.h" #include "qeglfswindow.h" +#include "qeglfscontext.h" -#include #include #include -#include - QT_BEGIN_NAMESPACE -QEglFSCompositor::QEglFSCompositor() - : m_rootWindow(0) -{ - m_updateTimer.setSingleShot(true); - m_updateTimer.setInterval(0); - connect(&m_updateTimer, SIGNAL(timeout()), SLOT(renderAll())); -} - -void QEglFSCompositor::schedule(QEglFSWindow *rootWindow) -{ - m_rootWindow = rootWindow; - if (!m_updateTimer.isActive()) - m_updateTimer.start(); -} - -void QEglFSCompositor::renderAll() -{ - Q_ASSERT(m_rootWindow); - QOpenGLContext *context = QEglFSBackingStore::makeRootCurrent(m_rootWindow); - - QEglFSScreen *screen = m_rootWindow->screen(); - QList windows = screen->windows(); - for (int i = 0; i < windows.size(); ++i) { - if (windows.at(i)->backingStore()) - render(windows.at(i), m_rootWindow); - } - - context->swapBuffers(m_rootWindow->window()); - context->doneCurrent(); -} - -void QEglFSCompositor::render(QEglFSWindow *window, QEglFSWindow *rootWindow) -{ - QEglFSBackingStore *rootBackingStore = rootWindow->backingStore(); - rootBackingStore->m_program->bind(); - - const GLfloat textureCoordinates[] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; - - QRectF sr = window->screen()->geometry(); - QRect r = window->window()->geometry(); - QPoint tl = r.topLeft(); - QPoint br = r.bottomRight(); - - GLfloat x1 = (tl.x() / sr.width()) * 2 - 1; - GLfloat x2 = (br.x() / sr.width()) * 2 - 1; - GLfloat y1 = ((sr.height() - tl.y()) / sr.height()) * 2 - 1; - GLfloat y2 = ((sr.height() - br.y()) / sr.height()) * 2 - 1; - - const GLfloat vertexCoordinates[] = { - x1, y1, - x2, y1, - x2, y2, - x1, y2 - }; - - glViewport(0, 0, sr.width(), sr.height()); - - glEnableVertexAttribArray(rootBackingStore->m_vertexCoordEntry); - glEnableVertexAttribArray(rootBackingStore->m_textureCoordEntry); - - glVertexAttribPointer(rootBackingStore->m_vertexCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates); - glVertexAttribPointer(rootBackingStore->m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates); - - glBindTexture(GL_TEXTURE_2D, window->backingStore()->m_texture); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - rootBackingStore->m_program->release(); - glBindTexture(GL_TEXTURE_2D, 0); - glDisableVertexAttribArray(rootBackingStore->m_vertexCoordEntry); - glDisableVertexAttribArray(rootBackingStore->m_textureCoordEntry); -} - -static QEglFSCompositor *compositor = 0; - -QEglFSCompositor *QEglFSCompositor::instance() -{ - if (!compositor) - compositor = new QEglFSCompositor; - return compositor; -} - QEglFSBackingStore::QEglFSBackingStore(QWindow *window) - : QPlatformBackingStore(window) - , m_window(static_cast(window->handle())) - , m_context(0) - , m_texture(0) - , m_program(0) + : QPlatformBackingStore(window), + m_window(static_cast(window->handle())), + m_texture(0) { m_window->setBackingStore(this); } -QEglFSBackingStore::~QEglFSBackingStore() -{ - delete m_program; - delete m_context; -} - QPaintDevice *QEglFSBackingStore::paintDevice() { return &m_image; @@ -186,7 +90,8 @@ void QEglFSBackingStore::updateTexture() // 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())); + 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()); @@ -207,63 +112,14 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo qWarning("QEglBackingStore::flush %p", window); #endif - m_window->create(); QEglFSWindow *rootWin = m_window->screen()->rootWindow(); - if (rootWin) { - makeRootCurrent(rootWin); - updateTexture(); - QEglFSCompositor::instance()->schedule(rootWin); - } -} - -void QEglFSBackingStore::makeCurrent() -{ - Q_ASSERT(m_window->hasNativeWindow()); - - QWindow *wnd = window(); - if (!m_context) { - m_context = new QOpenGLContext; - m_context->setFormat(wnd->requestedFormat()); - m_context->setScreen(wnd->screen()); - m_context->create(); - } + if (!rootWin) + return; - m_context->makeCurrent(wnd); -} - -QOpenGLContext *QEglFSBackingStore::makeRootCurrent(QEglFSWindow *rootWin) -{ - Q_ASSERT(rootWin->hasNativeWindow() && rootWin->isRasterRoot()); - - QEglFSBackingStore *rootBackingStore = rootWin->backingStore(); - rootBackingStore->makeCurrent(); - if (!rootBackingStore->m_program) { - 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, 0.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"; - - rootBackingStore->m_program = new QOpenGLShaderProgram; - - rootBackingStore->m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); - rootBackingStore->m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); - rootBackingStore->m_program->link(); - - rootBackingStore->m_vertexCoordEntry = rootBackingStore->m_program->attributeLocation("vertexCoordEntry"); - rootBackingStore->m_textureCoordEntry = rootBackingStore->m_program->attributeLocation("textureCoordEntry"); - } - return rootBackingStore->m_context; + m_window->create(); + rootWin->screen()->rootContext()->makeCurrent(rootWin->window()); + updateTexture(); + QEglFSCompositor::instance()->schedule(rootWin->screen()); } void QEglFSBackingStore::beginPaint(const QRegion &rgn) @@ -275,9 +131,14 @@ void QEglFSBackingStore::resize(const QSize &size, const QRegion &staticContents { Q_UNUSED(staticContents); + QEglFSWindow *rootWin = m_window->screen()->rootWindow(); + if (!rootWin) + return; + m_image = QImage(size, QImage::Format_RGB32); m_window->create(); - makeRootCurrent(m_window->screen()->rootWindow()); + + rootWin->screen()->rootContext()->makeCurrent(rootWin->window()); if (m_texture) glDeleteTextures(1, &m_texture); diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.h b/src/plugins/platforms/eglfs/qeglfsbackingstore.h index 39bdab1563..535428aac1 100644 --- a/src/plugins/platforms/eglfs/qeglfsbackingstore.h +++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.h @@ -46,41 +46,16 @@ #include #include -#include QT_BEGIN_NAMESPACE -class QOpenGLContext; class QOpenGLPaintDevice; -class QOpenGLShaderProgram; class QEglFSWindow; -class QEglFSCompositor : public QObject -{ - Q_OBJECT - -public: - QEglFSCompositor(); - - void schedule(QEglFSWindow *rootWindow); - - static QEglFSCompositor *instance(); - -private slots: - void renderAll(); - -private: - void render(QEglFSWindow *window, QEglFSWindow *rootWindow); - - QEglFSWindow *m_rootWindow; - QTimer m_updateTimer; -}; - class QEglFSBackingStore : public QPlatformBackingStore { public: QEglFSBackingStore(QWindow *window); - ~QEglFSBackingStore(); QPaintDevice *paintDevice(); @@ -89,21 +64,15 @@ public: void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); void resize(const QSize &size, const QRegion &staticContents); + uint texture() const { return m_texture; } + private: - void makeCurrent(); - static QOpenGLContext *makeRootCurrent(QEglFSWindow *rootWin); void updateTexture(); QEglFSWindow *m_window; - QOpenGLContext *m_context; QImage m_image; uint m_texture; QRegion m_dirty; - QOpenGLShaderProgram *m_program; - int m_vertexCoordEntry; - int m_textureCoordEntry; - - friend class QEglFSCompositor; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfscompositor.cpp b/src/plugins/platforms/eglfs/qeglfscompositor.cpp new file mode 100644 index 0000000000..9db43a57a1 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfscompositor.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** 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 "qeglfscompositor.h" +#include "qeglfswindow.h" +#include "qeglfscontext.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +static QEglFSCompositor *compositor = 0; + +QEglFSCompositor::QEglFSCompositor() + : m_screen(0), + m_program(0) +{ + Q_ASSERT(!compositor); + m_updateTimer.setSingleShot(true); + m_updateTimer.setInterval(0); + connect(&m_updateTimer, SIGNAL(timeout()), SLOT(renderAll())); +} + +QEglFSCompositor::~QEglFSCompositor() +{ + Q_ASSERT(compositor == this); + delete m_program; + compositor = 0; +} + +void QEglFSCompositor::schedule(QEglFSScreen *screen) +{ + m_screen = screen; + if (!m_updateTimer.isActive()) + m_updateTimer.start(); +} + +void QEglFSCompositor::renderAll() +{ + QEglFSWindow *rootWin = m_screen->rootWindow(); + if (!rootWin) + return; + + Q_ASSERT(rootWin->hasNativeWindow()); + QOpenGLContext *context = m_screen->rootContext(); + Q_ASSERT(context); + + context->makeCurrent(rootWin->window()); + ensureProgram(); + m_program->bind(); + + QList windows = m_screen->windows(); + for (int i = 0; i < windows.size(); ++i) { + QEglFSWindow *window = windows.at(i); + uint texture = window->texture(); + if (texture) + render(window, texture, window->isRaster()); + } + + m_program->release(); + context->swapBuffers(rootWin->window()); +} + +void QEglFSCompositor::ensureProgram() +{ + if (!m_program) { + 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, 0.0, 1.0);\n" + "}\n"; + + static const char *textureFragmentProgram = + "uniform sampler2D texture;\n" + "varying highp vec2 textureCoord;\n" + "uniform bool isRaster;\n" + "void main() {\n" + " lowp vec4 c = texture2D(texture, textureCoord);\n" + " gl_FragColor = isRaster ? c.bgra : c.rgba;\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_isRasterEntry = m_program->uniformLocation("isRaster"); + } +} + +void QEglFSCompositor::render(QEglFSWindow *window, uint texture, bool raster) +{ + const GLfloat textureCoordinates[] = { + 0, 0, + 1, 0, + 1, 1, + 0, 1 + }; + + QRectF sr = window->screen()->geometry(); + QRect r = window->window()->geometry(); + QPoint tl = r.topLeft(); + QPoint br = r.bottomRight(); + + GLfloat x1 = (tl.x() / sr.width()) * 2 - 1; + GLfloat x2 = (br.x() / sr.width()) * 2 - 1; + GLfloat y1 = ((sr.height() - tl.y()) / sr.height()) * 2 - 1; + GLfloat y2 = ((sr.height() - br.y()) / sr.height()) * 2 - 1; + + if (!raster) + qSwap(y1, y2); + + const GLfloat vertexCoordinates[] = { + x1, y1, + x2, y1, + x2, y2, + x1, y2 + }; + + glViewport(0, 0, sr.width(), sr.height()); + + glEnableVertexAttribArray(m_vertexCoordEntry); + glEnableVertexAttribArray(m_textureCoordEntry); + + glVertexAttribPointer(m_vertexCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates); + glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates); + + glBindTexture(GL_TEXTURE_2D, texture); + + m_program->setUniformValue(m_isRasterEntry, raster); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBindTexture(GL_TEXTURE_2D, 0); + glDisableVertexAttribArray(m_vertexCoordEntry); + glDisableVertexAttribArray(m_textureCoordEntry); +} + +QEglFSCompositor *QEglFSCompositor::instance() +{ + if (!compositor) + compositor = new QEglFSCompositor; + return compositor; +} + +void QEglFSCompositor::destroy() +{ + delete compositor; + compositor = 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfscompositor.h b/src/plugins/platforms/eglfs/qeglfscompositor.h new file mode 100644 index 0000000000..ade2e06031 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfscompositor.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** 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 QEGLFSCOMPOSITOR_H +#define QEGLFSCOMPOSITOR_H + +#include + +QT_BEGIN_NAMESPACE + +class QEglFSScreen; +class QEglFSWindow; +class QOpenGLShaderProgram; + +class QEglFSCompositor : public QObject +{ + Q_OBJECT + +public: + void schedule(QEglFSScreen *screen); + + static QEglFSCompositor *instance(); + static void destroy(); + +private slots: + void renderAll(); + +private: + QEglFSCompositor(); + ~QEglFSCompositor(); + + void render(QEglFSWindow *window, uint texture, bool raster); + void ensureProgram(); + + QEglFSScreen *m_screen; + QTimer m_updateTimer; + QOpenGLShaderProgram *m_program; + int m_vertexCoordEntry; + int m_textureCoordEntry; + int m_isRasterEntry; +}; + +QT_END_NAMESPACE + +#endif // QEGLFSCOMPOSITOR_H diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 45dccfa79f..67f0c35ed7 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -43,6 +43,7 @@ #include "qeglfswindow.h" #include "qeglfsbackingstore.h" +#include "qeglfscompositor.h" #include "qeglfshooks.h" #include @@ -75,8 +76,6 @@ QT_BEGIN_NAMESPACE -static void *eglContextForContext(QOpenGLContext *context); - QEglFSIntegration::QEglFSIntegration() : mFontDb(new QGenericUnixFontDatabase) , mServices(new QGenericUnixServices) @@ -108,8 +107,8 @@ QEglFSIntegration::QEglFSIntegration() QEglFSIntegration::~QEglFSIntegration() { + QEglFSCompositor::destroy(); delete mScreen; - eglTerminate(mDisplay); QEglFSHooks::hooks()->platformDestroy(); } @@ -131,9 +130,11 @@ bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) cons QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const { + QWindowSystemInterface::flushWindowSystemEvents(); QEglFSWindow *w = new QEglFSWindow(window); w->create(); - w->requestActivateWindow(); + if (window->type() != Qt::ToolTip) + w->requestActivateWindow(); return w; } @@ -263,15 +264,6 @@ void *QEglFSIntegration::nativeResourceForContext(const QByteArray &resource, QO return result; } -QPlatformNativeInterface::NativeResourceForContextFunction QEglFSIntegration::nativeResourceFunctionForContext(const QByteArray &resource) -{ - QByteArray lowerCaseResource = resource.toLower(); - if (lowerCaseResource == "get_egl_context") - return NativeResourceForContextFunction(eglContextForContext); - - return 0; -} - static void *eglContextForContext(QOpenGLContext *context) { Q_ASSERT(context); @@ -283,6 +275,15 @@ static void *eglContextForContext(QOpenGLContext *context) return handle->eglContext(); } +QPlatformNativeInterface::NativeResourceForContextFunction QEglFSIntegration::nativeResourceFunctionForContext(const QByteArray &resource) +{ + QByteArray lowerCaseResource = resource.toLower(); + if (lowerCaseResource == "get_egl_context") + return NativeResourceForContextFunction(eglContextForContext); + + return 0; +} + EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format) { class Chooser : public QEglConfigChooser { diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp index 62f764b392..bd3601bf06 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -47,9 +47,10 @@ QT_BEGIN_NAMESPACE QEglFSScreen::QEglFSScreen(EGLDisplay dpy) - : m_dpy(dpy) - , m_surface(EGL_NO_SURFACE) - , m_cursor(0) + : m_dpy(dpy), + m_surface(EGL_NO_SURFACE), + m_cursor(0), + m_rootContext(0) { #ifdef QEGL_EXTRA_DEBUG qWarning("QEglScreen %p\n", this); @@ -121,10 +122,23 @@ void QEglFSScreen::removeWindow(QEglFSWindow *window) m_windows.removeOne(window); } +void QEglFSScreen::moveToTop(QEglFSWindow *window) +{ + m_windows.removeOne(window); + m_windows.append(window); +} + +void QEglFSScreen::changeWindowIndex(QEglFSWindow *window, int newIdx) +{ + int idx = m_windows.indexOf(window); + if (idx != -1 && idx != newIdx) + m_windows.move(idx, newIdx); +} + QEglFSWindow *QEglFSScreen::rootWindow() { Q_FOREACH (QEglFSWindow *window, m_windows) { - if (window->isRasterRoot()) + if (window->hasNativeWindow()) return window; } return 0; diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h index bf7e88bd50..578a6cf20d 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.h +++ b/src/plugins/platforms/eglfs/qeglfsscreen.h @@ -50,9 +50,9 @@ QT_BEGIN_NAMESPACE -class QPlatformOpenGLContext; class QEglFSCursor; class QEglFSWindow; +class QOpenGLContext; class QEglFSScreen : public QPlatformScreen { @@ -77,7 +77,11 @@ public: QList windows() const { return m_windows; } void addWindow(QEglFSWindow *window); void removeWindow(QEglFSWindow *window); + void moveToTop(QEglFSWindow *window); + void changeWindowIndex(QEglFSWindow *window, int newIdx); QEglFSWindow *rootWindow(); + QOpenGLContext *rootContext() { return m_rootContext; } + void setRootContext(QOpenGLContext *context) { m_rootContext = context; } protected: void setPrimarySurface(EGLSurface surface); @@ -89,6 +93,7 @@ private: EGLSurface m_surface; QEglFSCursor *m_cursor; QList m_windows; + QOpenGLContext *m_rootContext; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 17ab68f747..70f0e437b2 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -42,9 +42,11 @@ #include "qeglfswindow.h" #include "qeglfshooks.h" #include "qeglfscursor.h" +#include "qeglfsbackingstore.h" #include #include #include +#include #include @@ -99,18 +101,21 @@ void QEglFSWindow::create() if (window()->surfaceType() == QSurface::RasterSurface) m_flags |= IsRaster; - // Stop if there is already a raster root window backed by a native window and - // surface. Other raster windows will not have their own native window, surface and - // context. Instead, they will be composited onto the root window's surface. - if (screen()->primarySurface() != EGL_NO_SURFACE) { - if (m_flags.testFlag(IsRaster) && screen()->rootWindow()->m_flags.testFlag(IsRaster)) + // Stop if there is already a window backed by a native window and surface. Additional + // raster windows will not have their own native window, surface and context. Instead, + // they will be composited onto the root window's surface. + QEglFSScreen *screen = this->screen(); + if (screen->primarySurface() != EGL_NO_SURFACE) { + if (m_flags.testFlag(IsRaster) && screen->rootWindow()->m_flags.testFlag(IsRaster)) return; -#ifndef Q_OS_ANDROID +#if !defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK) // We can have either a single OpenGL window or multiple raster windows. // Other combinations cannot work. qFatal("EGLFS: OpenGL windows cannot be mixed with others."); #endif + + return; } window()->setSurfaceType(QSurface::OpenGLSurface); @@ -118,31 +123,40 @@ void QEglFSWindow::create() setGeometry(QRect()); // will become fullscreen QWindowSystemInterface::handleExposeEvent(window(), geometry()); - EGLDisplay display = static_cast(screen())->display(); + EGLDisplay display = static_cast(screen)->display(); QSurfaceFormat platformFormat = QEglFSHooks::hooks()->surfaceFormatFor(window()->requestedFormat()); m_config = QEglFSIntegration::chooseConfig(display, platformFormat); m_format = q_glFormatFromConfig(display, m_config); resetSurface(); - if (screen()->primarySurface() == EGL_NO_SURFACE) { - screen()->setPrimarySurface(m_surface); - m_flags |= IsRasterRoot; + screen->setPrimarySurface(m_surface); + + if (m_flags.testFlag(IsRaster)) { + QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance()); + context->setFormat(window()->requestedFormat()); + context->setScreen(window()->screen()); + context->create(); + screen->setRootContext(context); } } void QEglFSWindow::destroy() { + QEglFSScreen *screen = this->screen(); if (m_flags.testFlag(HasNativeWindow)) { - QEglFSCursor *cursor = static_cast(screen()->cursor()); + QEglFSCursor *cursor = static_cast(screen->cursor()); if (cursor) cursor->resetResources(); - if (screen()->primarySurface() == m_surface) - screen()->setPrimarySurface(EGL_NO_SURFACE); + + if (screen->primarySurface() == m_surface) + screen->setPrimarySurface(EGL_NO_SURFACE); + invalidateSurface(); } + m_flags = 0; - screen()->removeWindow(this); + screen->removeWindow(this); } // The virtual functions resetSurface and invalidateSurface may get overridden @@ -182,20 +196,15 @@ void QEglFSWindow::setVisible(bool visible) } else { screen()->removeWindow(this); windows = screen()->windows(); - // try activating the window below if (windows.size()) windows.last()->requestActivateWindow(); } } - // trigger an update - QEglFSWindow *rootWin = screen()->rootWindow(); - if (rootWin) { - QWindowSystemInterface::handleExposeEvent(rootWin->window(), rootWin->window()->geometry()); - QWindowSystemInterface::flushWindowSystemEvents(); - } + QWindowSystemInterface::handleExposeEvent(window(), window()->geometry()); - QPlatformWindow::setVisible(visible); + if (visible) + QWindowSystemInterface::flushWindowSystemEvents(); } void QEglFSWindow::setGeometry(const QRect &r) @@ -229,14 +238,32 @@ WId QEglFSWindow::winId() const } void QEglFSWindow::requestActivateWindow() +{ + if (window()->type() != Qt::Desktop) + screen()->moveToTop(this); + + QWindowSystemInterface::handleWindowActivated(window()); + QWindowSystemInterface::handleExposeEvent(window(), window()->geometry()); +} + +void QEglFSWindow::raise() { if (window()->type() != Qt::Desktop) { - // move to the end of the list, to be on top - screen()->removeWindow(this); - screen()->addWindow(this); + screen()->moveToTop(this); + QWindowSystemInterface::handleExposeEvent(window(), window()->geometry()); } +} - QWindowSystemInterface::handleWindowActivated(window()); +void QEglFSWindow::lower() +{ + QList windows = screen()->windows(); + if (window()->type() != Qt::Desktop && windows.count() > 1) { + int idx = windows.indexOf(this); + if (idx > 0) { + screen()->changeWindowIndex(this, idx - 1); + QWindowSystemInterface::handleExposeEvent(windows.last()->window(), windows.last()->geometry()); + } + } } EGLSurface QEglFSWindow::surface() const @@ -259,4 +286,12 @@ QEglFSScreen *QEglFSWindow::screen() const return static_cast(QPlatformWindow::screen()); } +uint QEglFSWindow::texture() const +{ + if (m_backingStore) + return m_backingStore->texture(); + + return 0; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index 71c0ed5c27..ee3c194a7c 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -62,6 +62,8 @@ public: WId winId() const; void setVisible(bool visible); void requestActivateWindow(); + void raise(); + void lower(); EGLSurface surface() const; QSurfaceFormat format() const; @@ -73,11 +75,13 @@ public: void destroy(); bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); } - bool isRasterRoot() const { return m_flags.testFlag(IsRasterRoot); } + bool isRaster() const { return m_flags.testFlag(IsRaster); } QEglFSBackingStore *backingStore() { return m_backingStore; } void setBackingStore(QEglFSBackingStore *backingStore) { m_backingStore = backingStore; } + uint texture() const; + virtual void invalidateSurface(); virtual void resetSurface(); @@ -93,9 +97,8 @@ private: enum Flag { Created = 0x01, - HasNativeWindow = 0x02, - IsRaster = 0x04, - IsRasterRoot = 0x08 + IsRaster = 0x02, + HasNativeWindow = 0x04 }; Q_DECLARE_FLAGS(Flags, Flag); Flags m_flags; -- cgit v1.2.3