diff options
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); |