From f89f099c55576992b39a8021aace64ff32747624 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 13 Sep 2013 13:02:20 +0200 Subject: eglfs: Support multiple raster windows Allow widget apps with popups and multiple top-level widgets to function on the eglfs platform. GL and Quick2 apps are not affected. Instead of trying to create a native window and EGL surface for each window, do it only for the window that is created first. This first window is forced to fullscreen as usual. Later windows however are treated differently: These will not have a native window, surface or context, and keep their normal size. All the textures belonging to the raster windows are then rendered in one step, using a stacking order maintained based on visibility changes and window activation. Note that this will only help apps that create a main window first and have everything else inside that window or on top of it as menus, dialogs, popups, etc. Change-Id: Ia435458ba81bf3c35cc8f61bcb2d2a50cf17f0e3 Reviewed-by: Gunnar Sletta Reviewed-by: Andy Nichols --- src/plugins/platforms/eglfs/qeglfsbackingstore.cpp | 232 ++++++++++++++------- 1 file changed, 151 insertions(+), 81 deletions(-) (limited to 'src/plugins/platforms/eglfs/qeglfsbackingstore.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 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 ®ion, 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(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 ®ion, const QPo m_dirty = QRegion(); } +} - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); +void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, 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(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(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); -- cgit v1.2.3