summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/platforms/eglfs/eglfs.pri9
-rw-r--r--src/plugins/platforms/eglfs/qeglfsbackingstore.cpp232
-rw-r--r--src/plugins/platforms/eglfs/qeglfsbackingstore.h28
-rw-r--r--src/plugins/platforms/eglfs/qeglfscursor.cpp21
-rw-r--r--src/plugins/platforms/eglfs/qeglfscursor.h5
-rw-r--r--src/plugins/platforms/eglfs/qeglfshooks_x11.cpp7
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp25
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.h6
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.cpp22
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.h9
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.cpp152
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.h25
12 files changed, 386 insertions, 155 deletions
diff --git a/src/plugins/platforms/eglfs/eglfs.pri b/src/plugins/platforms/eglfs/eglfs.pri
index 44455ed3d8..4c066d6f26 100644
--- a/src/plugins/platforms/eglfs/eglfs.pri
+++ b/src/plugins/platforms/eglfs/eglfs.pri
@@ -2,12 +2,13 @@ QT += core-private gui-private platformsupport-private
#DEFINES += QEGL_EXTRA_DEBUG
-#Avoid X11 header collision
+# Avoid X11 header collision
DEFINES += MESA_EGL_NO_X11_HEADERS
-#To test the hooks on x11 (xlib), comment the above define too
-#EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_x11.cpp
-#LIBS += -lX11 -lX11-xcb -lxcb
+# Uncomment these to enable the X hooks, allowing to test the platform
+# plugin in a regular X11 environment (as long as EGL is available).
+# EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_x11.cpp
+# LIBS += -lX11 -lX11-xcb -lxcb
SOURCES += $$PWD/qeglfsintegration.cpp \
$$PWD/qeglfswindow.cpp \
diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp
index 35f699d975..ec2f4f9d91 100644
--- a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp
@@ -51,104 +51,123 @@
QT_BEGIN_NAMESPACE
-QEglFSBackingStore::QEglFSBackingStore(QWindow *window)
- : QPlatformBackingStore(window)
- , m_context(new QOpenGLContext)
- , m_texture(0)
- , m_program(0)
+QEglFSCompositor::QEglFSCompositor()
+ : m_rootWindow(0)
{
- m_context->setFormat(window->requestedFormat());
- m_context->setScreen(window->screen());
- m_context->create();
+ m_updateTimer.setSingleShot(true);
+ m_updateTimer.setInterval(0);
+ connect(&m_updateTimer, SIGNAL(timeout()), SLOT(renderAll()));
}
-QEglFSBackingStore::~QEglFSBackingStore()
+void QEglFSCompositor::schedule(QEglFSWindow *rootWindow)
{
- delete m_program;
- delete m_context;
+ m_rootWindow = rootWindow;
+ if (!m_updateTimer.isActive())
+ m_updateTimer.start();
}
-QPaintDevice *QEglFSBackingStore::paintDevice()
+void QEglFSCompositor::renderAll()
{
- return &m_image;
+ Q_ASSERT(m_rootWindow);
+ QOpenGLContext *context = QEglFSBackingStore::makeRootCurrent(m_rootWindow);
+
+ QEglFSScreen *screen = m_rootWindow->screen();
+ QList<QEglFSWindow *> 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 QEglFSBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+void QEglFSCompositor::render(QEglFSWindow *window, QEglFSWindow *rootWindow)
{
- Q_UNUSED(region);
- Q_UNUSED(offset);
+ QEglFSBackingStore *rootBackingStore = rootWindow->backingStore();
+ rootBackingStore->m_program->bind();
- makeCurrent();
+ const GLfloat textureCoordinates[] = {
+ 0, 0,
+ 1, 0,
+ 1, 1,
+ 0, 1
+ };
QRectF sr = window->screen()->geometry();
- glViewport(0, 0, sr.width(), sr.height());
+ QRect r = window->window()->geometry();
+ QPoint tl = r.topLeft();
+ QPoint br = r.bottomRight();
-#ifdef QEGL_EXTRA_DEBUG
- qWarning("QEglBackingStore::flush %p", window);
-#endif
+ 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 (!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";
+ const GLfloat vertexCoordinates[] = {
+ x1, y1,
+ x2, y1,
+ x2, y2,
+ x1, y2
+ };
- static const char *textureFragmentProgram =
- "uniform sampler2D texture;\n"
- "varying highp vec2 textureCoord;\n"
- "void main() {\n"
- " gl_FragColor = texture2D(texture, textureCoord).bgra;\n"
- "}\n";
+ glViewport(0, 0, sr.width(), sr.height());
- m_program = new QOpenGLShaderProgram;
+ glEnableVertexAttribArray(rootBackingStore->m_vertexCoordEntry);
+ glEnableVertexAttribArray(rootBackingStore->m_textureCoordEntry);
- m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
- m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
- m_program->link();
+ glVertexAttribPointer(rootBackingStore->m_vertexCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
+ glVertexAttribPointer(rootBackingStore->m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
- m_vertexCoordEntry = m_program->attributeLocation("vertexCoordEntry");
- m_textureCoordEntry = m_program->attributeLocation("textureCoordEntry");
- }
+ glBindTexture(GL_TEXTURE_2D, window->backingStore()->m_texture);
- m_program->bind();
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- const GLfloat textureCoordinates[] = {
- 0, 1,
- 1, 1,
- 1, 0,
- 0, 0
- };
+ rootBackingStore->m_program->release();
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisableVertexAttribArray(rootBackingStore->m_vertexCoordEntry);
+ glDisableVertexAttribArray(rootBackingStore->m_textureCoordEntry);
+}
- QRectF r = window->geometry();
+static QEglFSCompositor *compositor = 0;
- GLfloat x1 = (r.left() / sr.width()) * 2 - 1;
- GLfloat x2 = (r.right() / sr.width()) * 2 - 1;
- GLfloat y1 = (r.top() / sr.height()) * 2 - 1;
- GLfloat y2 = (r.bottom() / sr.height()) * 2 - 1;
+QEglFSCompositor *QEglFSCompositor::instance()
+{
+ if (!compositor)
+ compositor = new QEglFSCompositor;
+ return compositor;
+}
- const GLfloat vertexCoordinates[] = {
- x1, y1,
- x2, y1,
- x2, y2,
- x1, y2
- };
+QEglFSBackingStore::QEglFSBackingStore(QWindow *window)
+ : QPlatformBackingStore(window)
+ , m_window(static_cast<QEglFSWindow *>(window->handle()))
+ , m_context(0)
+ , m_texture(0)
+ , m_program(0)
+{
+ m_window->setBackingStore(this);
+}
- glEnableVertexAttribArray(m_vertexCoordEntry);
- glEnableVertexAttribArray(m_textureCoordEntry);
+QEglFSBackingStore::~QEglFSBackingStore()
+{
+ delete m_program;
+ delete m_context;
+}
- glVertexAttribPointer(m_vertexCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
- glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
+QPaintDevice *QEglFSBackingStore::paintDevice()
+{
+ return &m_image;
+}
+void QEglFSBackingStore::updateTexture()
+{
glBindTexture(GL_TEXTURE_2D, m_texture);
if (!m_dirty.isNull()) {
+ QRegion fixed;
QRect imageRect = m_image.rect();
+ m_dirty |= imageRect;
- QRegion fixed;
foreach (const QRect &rect, m_dirty.rects()) {
// intersect with image rect to be sure
QRect r = imageRect & rect;
@@ -176,32 +195,80 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion &region, const QPo
m_dirty = QRegion();
}
+}
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+void QEglFSBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(window);
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
- m_program->release();
- glBindTexture(GL_TEXTURE_2D, 0);
- glDisableVertexAttribArray(m_vertexCoordEntry);
- glDisableVertexAttribArray(m_textureCoordEntry);
+#ifdef QEGL_EXTRA_DEBUG
+ qWarning("QEglBackingStore::flush %p", window);
+#endif
- // draw the cursor
- if (QEglFSCursor *cursor = static_cast<QEglFSCursor *>(window->screen()->handle()->cursor()))
- cursor->paintOnScreen();
+ m_window->create();
+ QEglFSWindow *rootWin = m_window->screen()->rootWindow();
+ if (rootWin) {
+ makeRootCurrent(rootWin);
+ updateTexture();
+ QEglFSCompositor::instance()->schedule(rootWin);
+ }
+}
- m_context->swapBuffers(window);
+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();
+ }
- m_context->doneCurrent();
+ m_context->makeCurrent(wnd);
}
-void QEglFSBackingStore::makeCurrent()
+QOpenGLContext *QEglFSBackingStore::makeRootCurrent(QEglFSWindow *rootWin)
{
- (static_cast<QEglFSWindow *>(window()->handle()))->create();
- m_context->makeCurrent(window());
+ 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;
}
void QEglFSBackingStore::beginPaint(const QRegion &rgn)
{
- m_dirty = m_dirty | rgn;
+ m_dirty |= rgn;
}
void QEglFSBackingStore::resize(const QSize &size, const QRegion &staticContents)
@@ -209,9 +276,12 @@ void QEglFSBackingStore::resize(const QSize &size, const QRegion &staticContents
Q_UNUSED(staticContents);
m_image = QImage(size, QImage::Format_RGB32);
- makeCurrent();
+ m_window->create();
+ makeRootCurrent(m_window->screen()->rootWindow());
+
if (m_texture)
glDeleteTextures(1, &m_texture);
+
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.h b/src/plugins/platforms/eglfs/qeglfsbackingstore.h
index 5d86814df9..39bdab1563 100644
--- a/src/plugins/platforms/eglfs/qeglfsbackingstore.h
+++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.h
@@ -46,12 +46,35 @@
#include <QImage>
#include <QRegion>
+#include <QTimer>
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
{
@@ -68,7 +91,10 @@ public:
private:
void makeCurrent();
+ static QOpenGLContext *makeRootCurrent(QEglFSWindow *rootWin);
+ void updateTexture();
+ QEglFSWindow *m_window;
QOpenGLContext *m_context;
QImage m_image;
uint m_texture;
@@ -76,6 +102,8 @@ private:
QOpenGLShaderProgram *m_program;
int m_vertexCoordEntry;
int m_textureCoordEntry;
+
+ friend class QEglFSCompositor;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfscursor.cpp b/src/plugins/platforms/eglfs/qeglfscursor.cpp
index f54e077311..c00e86de35 100644
--- a/src/plugins/platforms/eglfs/qeglfscursor.cpp
+++ b/src/plugins/platforms/eglfs/qeglfscursor.cpp
@@ -63,11 +63,20 @@ QEglFSCursor::QEglFSCursor(QEglFSScreen *screen)
QEglFSCursor::~QEglFSCursor()
{
+ resetResources();
+}
+
+void QEglFSCursor::resetResources()
+{
if (QOpenGLContext::currentContext()) {
glDeleteProgram(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;
}
static GLuint createShader(GLenum shaderType, const char *program)
@@ -201,9 +210,9 @@ bool QEglFSCursor::setCurrentCursor(QCursor *cursor)
return false;
if (m_cursor.shape == Qt::BitmapCursor) {
- m_cursor.customCursorImage = QImage(); // in case render() never uploaded it
+ 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,
@@ -221,6 +230,7 @@ bool QEglFSCursor::setCurrentCursor(QCursor *cursor)
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;
@@ -255,7 +265,7 @@ void QEglFSCursor::pointerEvent(const QMouseEvent &event)
if (event.type() != QEvent::MouseMove)
return;
const QRect oldCursorRect = cursorRect();
- m_cursor.pos = event.pos();
+ m_cursor.pos = event.screenPos().toPoint();
update(oldCursorRect | cursorRect());
}
@@ -280,18 +290,17 @@ void QEglFSCursor::draw(const QRectF &r)
if (!m_cursorAtlas.texture) {
createCursorTexture(&m_cursorAtlas.texture, m_cursorAtlas.image);
- m_cursorAtlas.image = QImage();
if (m_cursor.shape != Qt::BitmapCursor)
m_cursor.texture = m_cursorAtlas.texture;
}
}
- if (m_cursor.shape == Qt::BitmapCursor && !m_cursor.customCursorImage.isNull()) {
+ 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.customCursorImage = QImage();
+ m_cursor.customCursorPending = false;
}
Q_ASSERT(m_cursor.texture);
diff --git a/src/plugins/platforms/eglfs/qeglfscursor.h b/src/plugins/platforms/eglfs/qeglfscursor.h
index fdbffde14b..51a34e041d 100644
--- a/src/plugins/platforms/eglfs/qeglfscursor.h
+++ b/src/plugins/platforms/eglfs/qeglfscursor.h
@@ -69,6 +69,8 @@ public:
virtual void paintOnScreen();
+ void resetResources();
+
protected:
#ifndef QT_NO_CURSOR
bool setCurrentCursor(QCursor *cursor);
@@ -80,7 +82,7 @@ protected:
// current cursor information
struct Cursor {
- Cursor() : texture(0), shape(Qt::BlankCursor), customCursorTexture(0) { }
+ 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
@@ -89,6 +91,7 @@ protected:
QImage customCursorImage;
QPoint pos; // current cursor position
uint customCursorTexture;
+ bool customCursorPending;
} m_cursor;
private:
diff --git a/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp b/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp
index 50f8d0acb6..a3f94fb5b4 100644
--- a/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp
+++ b/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp
@@ -194,8 +194,11 @@ void EventReader::run()
const xcb_atom_t *atoms = m_hooks->atoms();
if (client->format == 32
&& client->type == atoms[Atoms::WM_PROTOCOLS]
- && client->data.data32[0] == atoms[Atoms::WM_DELETE_WINDOW])
- QWindowSystemInterface::handleCloseEvent(m_hooks->platformWindow()->window());
+ && client->data.data32[0] == atoms[Atoms::WM_DELETE_WINDOW]) {
+ QWindow *window = m_hooks->platformWindow() ? m_hooks->platformWindow()->window() : 0;
+ if (window)
+ QWindowSystemInterface::handleCloseEvent(window);
+ }
break;
}
default:
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index 487a2a15ec..12658e6d01 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -49,6 +49,7 @@
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#include <QtPlatformSupport/private/qgenericunixservices_p.h>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
@@ -77,7 +78,9 @@ QT_BEGIN_NAMESPACE
static void *eglContextForContext(QOpenGLContext *context);
QEglFSIntegration::QEglFSIntegration()
- : mEventDispatcher(createUnixEventDispatcher()), mFontDb(new QGenericUnixFontDatabase())
+ : mEventDispatcher(createUnixEventDispatcher()),
+ mFontDb(new QGenericUnixFontDatabase),
+ mServices(new QGenericUnixServices)
{
QGuiApplicationPrivate::instance()->setEventDispatcher(mEventDispatcher);
@@ -161,7 +164,7 @@ QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOf
QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const
{
- return mFontDb;
+ return mFontDb.data();
}
QAbstractEventDispatcher *QEglFSIntegration::guiThreadEventDispatcher() const
@@ -171,10 +174,18 @@ QAbstractEventDispatcher *QEglFSIntegration::guiThreadEventDispatcher() const
QVariant QEglFSIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
{
- if (hint == QPlatformIntegration::ShowIsFullScreen)
- return true;
+ switch (hint)
+ {
+ case QPlatformIntegration::ShowIsFullScreen:
+ return mScreen->rootWindow() == 0;
+ default:
+ return QPlatformIntegration::styleHint(hint);
+ }
+}
- return QPlatformIntegration::styleHint(hint);
+QPlatformServices *QEglFSIntegration::services() const
+{
+ return mServices.data();
}
QPlatformNativeInterface *QEglFSIntegration::nativeInterface() const
@@ -187,7 +198,7 @@ void *QEglFSIntegration::nativeResourceForIntegration(const QByteArray &resource
QByteArray lowerCaseResource = resource.toLower();
if (lowerCaseResource == "egldisplay")
- return static_cast<QEglFSScreen *>(mScreen)->display();
+ return mScreen->display();
return 0;
}
@@ -200,7 +211,7 @@ void *QEglFSIntegration::nativeResourceForWindow(const QByteArray &resource, QWi
if (window && window->handle())
return static_cast<QEglFSScreen *>(window->handle()->screen())->display();
else
- return static_cast<QEglFSScreen *>(mScreen)->display();
+ return mScreen->display();
}
return 0;
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h
index dd85788bd8..c6265bb970 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.h
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.h
@@ -65,6 +65,7 @@ public:
QPlatformNativeInterface *nativeInterface() const;
QPlatformFontDatabase *fontDatabase() const;
+ QPlatformServices *services() const;
QAbstractEventDispatcher *guiThreadEventDispatcher() const;
@@ -87,8 +88,9 @@ public:
private:
EGLDisplay mDisplay;
QAbstractEventDispatcher *mEventDispatcher;
- QPlatformFontDatabase *mFontDb;
- QPlatformScreen *mScreen;
+ QScopedPointer<QPlatformFontDatabase> mFontDb;
+ QScopedPointer<QPlatformServices> mServices;
+ QEglFSScreen *mScreen;
QPlatformInputContext *mInputContext;
};
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
index a726215e67..62f764b392 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
: m_dpy(dpy)
- , m_surface(0)
+ , m_surface(EGL_NO_SURFACE)
, m_cursor(0)
{
#ifdef QEGL_EXTRA_DEBUG
@@ -110,4 +110,24 @@ void QEglFSScreen::setPrimarySurface(EGLSurface surface)
m_surface = surface;
}
+void QEglFSScreen::addWindow(QEglFSWindow *window)
+{
+ if (!m_windows.contains(window))
+ m_windows.append(window);
+}
+
+void QEglFSScreen::removeWindow(QEglFSWindow *window)
+{
+ m_windows.removeOne(window);
+}
+
+QEglFSWindow *QEglFSScreen::rootWindow()
+{
+ Q_FOREACH (QEglFSWindow *window, m_windows) {
+ if (window->isRasterRoot())
+ return window;
+ }
+ return 0;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h
index 06cafa20c8..bf7e88bd50 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.h
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.h
@@ -52,8 +52,9 @@ QT_BEGIN_NAMESPACE
class QPlatformOpenGLContext;
class QEglFSCursor;
+class QEglFSWindow;
-class QEglFSScreen : public QPlatformScreen //huh: FullScreenScreen ;) just to follow namespace
+class QEglFSScreen : public QPlatformScreen
{
public:
QEglFSScreen(EGLDisplay display);
@@ -73,6 +74,11 @@ public:
EGLDisplay display() const { return m_dpy; }
EGLSurface primarySurface() const { return m_surface; }
+ QList<QEglFSWindow *> windows() const { return m_windows; }
+ void addWindow(QEglFSWindow *window);
+ void removeWindow(QEglFSWindow *window);
+ QEglFSWindow *rootWindow();
+
protected:
void setPrimarySurface(EGLSurface surface);
@@ -82,6 +88,7 @@ private:
EGLDisplay m_dpy;
EGLSurface m_surface;
QEglFSCursor *m_cursor;
+ QList<QEglFSWindow *> m_windows;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp
index d66f175920..888de058ad 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp
@@ -41,6 +41,7 @@
#include "qeglfswindow.h"
#include "qeglfshooks.h"
+#include "qeglfscursor.h"
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformintegration.h>
#include <private/qguiapplication_p.h>
@@ -55,12 +56,13 @@ QEglFSWindow::QEglFSWindow(QWindow *w)
: QPlatformWindow(w)
, m_surface(0)
, m_window(0)
- , has_window(false)
+ , m_wid(0)
+ , m_backingStore(0)
+ , m_flags(0)
{
#ifdef QEGL_EXTRA_DEBUG
qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_window));
#endif
- w->setSurfaceType(QSurface::OpenGLSurface);
}
QEglFSWindow::~QEglFSWindow()
@@ -68,17 +70,23 @@ QEglFSWindow::~QEglFSWindow()
destroy();
}
-static inline bool supportsMultipleWindows()
+static WId newWId()
{
- return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows);
+ static WId id = 0;
+
+ if (id == std::numeric_limits<WId>::max())
+ qWarning("EGLFS: Out of window IDs");
+
+ return ++id;
}
void QEglFSWindow::create()
{
- if (has_window)
+ if (m_flags.testFlag(Created))
return;
- setWindowState(Qt::WindowFullScreen);
+ m_flags = Created;
+ m_wid = newWId();
if (window()->type() == Qt::Desktop) {
QRect rect(QPoint(), QEglFSHooks::hooks()->screenSize());
@@ -87,94 +95,142 @@ void QEglFSWindow::create()
return;
}
- if (!supportsMultipleWindows() && screen()->primarySurface()) {
- qFatal("EGLFS: Multiple windows are not supported");
- return;
+ // Save the original surface type before changing to OpenGLSurface.
+ 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))
+ return;
+
+#ifndef Q_OS_ANDROID
+ // 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
}
- EGLDisplay display = (static_cast<QEglFSScreen *>(window()->screen()->handle()))->display();
+ window()->setSurfaceType(QSurface::OpenGLSurface);
+ setGeometry(screen()->availableGeometry());
+ QWindowSystemInterface::handleExposeEvent(window(), QRegion(screen()->availableGeometry()));
+
+ EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
QSurfaceFormat platformFormat = QEglFSHooks::hooks()->surfaceFormatFor(window()->requestedFormat());
m_config = QEglFSIntegration::chooseConfig(display, platformFormat);
m_format = q_glFormatFromConfig(display, m_config);
+
resetSurface();
+
+ m_flags |= HasNativeWindow;
+ if (screen()->primarySurface() == EGL_NO_SURFACE) {
+ screen()->setPrimarySurface(m_surface);
+ m_flags |= IsRasterRoot;
+ }
+}
+
+void QEglFSWindow::destroy()
+{
+ if (m_flags.testFlag(HasNativeWindow)) {
+ QEglFSCursor *cursor = static_cast<QEglFSCursor *>(screen()->cursor());
+ if (cursor)
+ cursor->resetResources();
+ if (screen()->primarySurface() == m_surface)
+ screen()->setPrimarySurface(EGL_NO_SURFACE);
+ invalidateSurface();
+ }
+ m_flags = 0;
+ screen()->removeWindow(this);
}
+// The virtual functions resetSurface and invalidateSurface may get overridden
+// in derived classes, for example in the Android port, to perform the native
+// window and surface creation differently.
+
void QEglFSWindow::invalidateSurface()
{
- // Native surface has been deleted behind our backs
- has_window = false;
- if (m_surface != 0) {
- EGLDisplay display = (static_cast<QEglFSScreen *>(window()->screen()->handle()))->display();
+ if (m_surface != EGL_NO_SURFACE) {
+ EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
eglDestroySurface(display, m_surface);
- m_surface = 0;
+ m_surface = EGL_NO_SURFACE;
}
+ QEglFSHooks::hooks()->destroyNativeWindow(m_window);
+ m_window = 0;
}
void QEglFSWindow::resetSurface()
{
EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
-
m_window = QEglFSHooks::hooks()->createNativeWindow(this, QEglFSHooks::hooks()->screenSize(), m_format);
- has_window = true;
m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL);
-
if (m_surface == EGL_NO_SURFACE) {
EGLint error = eglGetError();
eglTerminate(display);
qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error);
}
-
- screen()->setPrimarySurface(m_surface);
}
-void QEglFSWindow::destroy()
+void QEglFSWindow::setVisible(bool visible)
{
- if (m_surface) {
- EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
- eglDestroySurface(display, m_surface);
-
- if (!supportsMultipleWindows()) {
- // ours must be the primary surface
- screen()->setPrimarySurface(0);
+ QList<QEglFSWindow *> windows = screen()->windows();
+
+ if (window()->type() != Qt::Desktop) {
+ if (visible) {
+ screen()->addWindow(this);
+ } else {
+ screen()->removeWindow(this);
+ windows = screen()->windows();
+ // try activating the window below
+ if (windows.size())
+ windows.last()->requestActivateWindow();
}
-
- m_surface = 0;
}
- if (has_window) {
- QEglFSHooks::hooks()->destroyNativeWindow(m_window);
- has_window = false;
+ // trigger an update
+ QEglFSWindow *rootWin = screen()->rootWindow();
+ if (rootWin) {
+ QWindowSystemInterface::handleExposeEvent(rootWin->window(), rootWin->window()->geometry());
+ QWindowSystemInterface::flushWindowSystemEvents();
}
+
+ QPlatformWindow::setVisible(visible);
}
-void QEglFSWindow::setGeometry(const QRect &)
+void QEglFSWindow::setGeometry(const QRect &r)
{
- // We only support full-screen windows
- QRect rect(screen()->availableGeometry());
+ QRect rect;
+ if (m_flags.testFlag(HasNativeWindow))
+ rect = screen()->availableGeometry();
+ else
+ rect = r;
+
QPlatformWindow::setGeometry(rect);
- QWindowSystemInterface::handleGeometryChange(window(), rect);
- QWindowSystemInterface::handleExposeEvent(window(), QRegion(rect));
+
+ if (rect != r)
+ QWindowSystemInterface::handleGeometryChange(window(), rect);
}
-void QEglFSWindow::setWindowState(Qt::WindowState)
+WId QEglFSWindow::winId() const
{
- setGeometry(QRect());
+ return m_wid;
}
-WId QEglFSWindow::winId() const
+void QEglFSWindow::requestActivateWindow()
{
- // Return a fake WId for desktop windows.
- if (window()->type() == Qt::Desktop)
- return std::numeric_limits<WId>::max();
+ if (window()->type() != Qt::Desktop) {
+ // move to the end of the list, to be on top
+ screen()->removeWindow(this);
+ screen()->addWindow(this);
+ }
- return WId(m_window);
+ QWindowSystemInterface::handleWindowActivated(window());
}
EGLSurface QEglFSWindow::surface() const
{
- if (!supportsMultipleWindows())
- return screen()->primarySurface();
- return m_surface;
+ return m_surface != EGL_NO_SURFACE ? m_surface : screen()->primarySurface();
}
QSurfaceFormat QEglFSWindow::format() const
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h
index 936537807a..783ae414d6 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.h
+++ b/src/plugins/platforms/eglfs/qeglfswindow.h
@@ -49,6 +49,8 @@
QT_BEGIN_NAMESPACE
+class QEglFSBackingStore;
+
class QEglFSWindow : public QPlatformWindow
{
public:
@@ -56,8 +58,9 @@ public:
~QEglFSWindow();
void setGeometry(const QRect &);
- void setWindowState(Qt::WindowState state);
WId winId() const;
+ void setVisible(bool visible);
+ void requestActivateWindow();
EGLSurface surface() const;
QSurfaceFormat format() const;
@@ -67,6 +70,12 @@ public:
void create();
void destroy();
+ bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); }
+ bool isRasterRoot() const { return m_flags.testFlag(IsRasterRoot); }
+
+ QEglFSBackingStore *backingStore() { return m_backingStore; }
+ void setBackingStore(QEglFSBackingStore *backingStore) { m_backingStore = backingStore; }
+
virtual void invalidateSurface();
virtual void resetSurface();
@@ -77,7 +86,19 @@ protected:
private:
EGLConfig m_config;
QSurfaceFormat m_format;
- bool has_window;
+ WId m_wid;
+ QEglFSBackingStore *m_backingStore;
+
+ enum Flag {
+ Created = 0x01,
+ HasNativeWindow = 0x02,
+ IsRaster = 0x04,
+ IsRasterRoot = 0x08
+ };
+ Q_DECLARE_FLAGS(Flags, Flag);
+ Flags m_flags;
};
+
QT_END_NAMESPACE
+
#endif // QEGLFSWINDOW_H