summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@digia.com>2013-09-13 13:02:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-20 12:05:08 +0200
commitf89f099c55576992b39a8021aace64ff32747624 (patch)
treeedefe8cefb81d63ef60440608112ee67ad837960 /src/plugins/platforms/eglfs/qeglfsbackingstore.cpp
parentcfd52842492d12af26d897e0f893c80b2df5945a (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.cpp232
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 &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);