diff options
author | Laszlo Agocs <laszlo.agocs@digia.com> | 2013-09-13 13:02:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-20 12:05:08 +0200 |
commit | f89f099c55576992b39a8021aace64ff32747624 (patch) | |
tree | edefe8cefb81d63ef60440608112ee67ad837960 /src/plugins/platforms/eglfs/qeglfsbackingstore.cpp | |
parent | cfd52842492d12af26d897e0f893c80b2df5945a (diff) |
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 <gunnar.sletta@digia.com>
Reviewed-by: Andy Nichols <andy.nichols@digia.com>
Diffstat (limited to 'src/plugins/platforms/eglfs/qeglfsbackingstore.cpp')
-rw-r--r-- | src/plugins/platforms/eglfs/qeglfsbackingstore.cpp | 232 |
1 files changed, 151 insertions, 81 deletions
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 ®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<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 ®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<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); |