diff options
author | Gunnar Sletta <gunnar.sletta@jollamobile.com> | 2014-01-18 07:40:21 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-01-21 14:09:18 +0100 |
commit | 36ff0f303b79dcd7aae93d5a73dfc1f179ac5560 (patch) | |
tree | 786453094160454edd96020901ef63a9bf9a0905 /examples | |
parent | bbf7285b669b105c7ccb6629d963b5e2584453d8 (diff) | |
download | qtwayland-36ff0f303b79dcd7aae93d5a73dfc1f179ac5560.tar.gz qtwayland-36ff0f303b79dcd7aae93d5a73dfc1f179ac5560.tar.bz2 qtwayland-36ff0f303b79dcd7aae93d5a73dfc1f179ac5560.zip |
Fix buffer handling.
The surface now has a distinct back and front buffer. Front means it
is on the screen and being used as a texture. Back means it should be
put to screen in the next updatePaintNode().
For the purpose of QML and GUI-thread properties, the 'back' buffer is
what contains the correct properties as it is what it will eventually
be rendered with. For the purpose of rendering, the front buffer
contains the right texture. If no back buffer is present, then there
was no changes and front buffer applies to both.
The Surface's buffer queue has been updated to only fire damage and
advance once we swap back buffer to front buffer which happens during
updatePaintNode(). The fact that the buffer advancing happens during
sync also means that we are releasing buffers back to the client as
soon as another buffer is ready to be displayed in the compositor.
This is "half a frame" earlier than the current implementation (which
releases after the next swap). We consider this safe because:
- The compositor has a new buffer to display and does not need the
old one.
- If the GPU is not done rasterizing the scanout buffer for the
previous frame, it should hold a read-lock on the buffer so
preventing the client from starting a render to it. If this
assumption fails on any hardware we can make the time of
buffer-advance optional. Either during "sync" or during "after
rendering" as it is today, but "after rendering" will not offer any
guarantee, just more time, resulting in a higher chance of the
buffers being ready. Aka, without an internal read-lock and no
fence mechanism, there is no guarantee.
Texture cleanup is now explicit as we have a well defined location to
clean up textures, during updatePaintNode(). This avoids cleanup
issues which previously existed as buffer cleanup was happening on the
GUI thread. Surface and Buffer destruction coming over wayland is
queued up in compositor and handled before the next "sync", when it is
safe to do so.
The change also removes doUpdate, postBuffer and frameSwappedInternal
as these are no longer used. Direct rendering will need to be
considered in a new light with the new buffering scheme, and anyway
needs work.
Change-Id: I2db0385b4b8859f96caba374f3530448178e1473
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/qwidget-compositor/main.cpp | 13 | ||||
-rw-r--r-- | examples/qwindow-compositor/qwindowcompositor.cpp | 23 | ||||
-rw-r--r-- | examples/qwindow-compositor/qwindowcompositor.h | 2 |
3 files changed, 27 insertions, 11 deletions
diff --git a/examples/qwidget-compositor/main.cpp b/examples/qwidget-compositor/main.cpp index 2c58fe98..1badb06a 100644 --- a/examples/qwidget-compositor/main.cpp +++ b/examples/qwidget-compositor/main.cpp @@ -139,6 +139,9 @@ protected: GLuint texture = 0; QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions(); + QSize windowSize = surface->size(); + surface->advanceBufferQueue(); + if (!m_surfaceCompositorFbo) functions->glGenFramebuffers(1,&m_surfaceCompositorFbo); @@ -152,7 +155,7 @@ protected: functions->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - paintChildren(surface,surface); + paintChildren(surface,surface,windowSize); functions->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); @@ -160,7 +163,7 @@ protected: return texture; } - void paintChildren(QWaylandSurface *surface, QWaylandSurface *window) { + void paintChildren(QWaylandSurface *surface, QWaylandSurface *window, const QSize &windowSize) { if (surface->subSurfaces().size() == 0) return; @@ -170,6 +173,7 @@ protected: QWaylandSurface *subSurface = i.next(); QPointF p = subSurface->mapTo(window,QPoint(0,0)); QSize size = subSurface->size(); + subSurface->advanceBufferQueue(); if (size.isValid()) { GLuint texture = 0; if (subSurface->type() == QWaylandSurface::Texture) { @@ -177,9 +181,9 @@ protected: } else if (surface->type() == QWaylandSurface::Shm ) { texture = m_textureCache->bindTexture(context()->contextHandle(), surface->image()); } - m_textureBlitter->drawTexture(texture,QRect(p.toPoint(),size),window->size(),0,window->isYInverted(),subSurface->isYInverted()); + m_textureBlitter->drawTexture(texture,QRect(p.toPoint(),size),windowSize,0,window->isYInverted(),subSurface->isYInverted()); } - paintChildren(subSurface,window); + paintChildren(subSurface,window,windowSize); } } #else //hmmm, this is actually untested :( @@ -220,6 +224,7 @@ protected: p.drawPixmap(rect(), m_backgroundScaled); #ifdef QT_COMPOSITOR_WAYLAND_GL + cleanupGraphicsResources(); if (!m_textureCache) { m_textureCache = new QOpenGLTextureCache(context()->contextHandle()); } diff --git a/examples/qwindow-compositor/qwindowcompositor.cpp b/examples/qwindow-compositor/qwindowcompositor.cpp index 79d5b111..19f7ce5e 100644 --- a/examples/qwindow-compositor/qwindowcompositor.cpp +++ b/examples/qwindow-compositor/qwindowcompositor.cpp @@ -252,6 +252,9 @@ GLuint QWindowCompositor::composeSurface(QWaylandSurface *surface, bool *texture { GLuint texture = 0; + QSize windowSize = surface->size(); + surface->advanceBufferQueue(); + QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions(); functions->glBindFramebuffer(GL_FRAMEBUFFER, m_surface_fbo); @@ -265,15 +268,17 @@ GLuint QWindowCompositor::composeSurface(QWaylandSurface *surface, bool *texture functions->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - paintChildren(surface,surface); + paintChildren(surface, surface,windowSize); functions->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,0, 0); functions->glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return texture; } -void QWindowCompositor::paintChildren(QWaylandSurface *surface, QWaylandSurface *window) { +void QWindowCompositor::paintChildren(QWaylandSurface *surface, QWaylandSurface *window, const QSize &windowSize) { if (surface->subSurfaces().size() == 0) return; @@ -282,19 +287,22 @@ void QWindowCompositor::paintChildren(QWaylandSurface *surface, QWaylandSurface while (i.hasNext()) { QWaylandSurface *subSurface = i.next(); QPointF p = subSurface->mapTo(window,QPointF(0,0)); - if (subSurface->size().isValid()) { + QSize subSize = subSurface->size(); + subSurface->advanceBufferQueue(); + if (subSize.isValid()) { GLuint texture = 0; if (subSurface->type() == QWaylandSurface::Texture) { texture = subSurface->texture(); } else if (surface->type() == QWaylandSurface::Shm) { texture = textureFromImage(subSurface->image()); } - QRect geo(p.toPoint(),subSurface->size()); - m_textureBlitter->drawTexture(texture,geo,window->size(),0,window->isYInverted(),subSurface->isYInverted()); + QRect geo(p.toPoint(),subSize); + if (texture > 0) + m_textureBlitter->drawTexture(texture,geo,windowSize,0,window->isYInverted(),subSurface->isYInverted()); if (surface->type() == QWaylandSurface::Shm) glDeleteTextures(1, &texture); } - paintChildren(subSurface,window); + paintChildren(subSurface,window,windowSize); } } @@ -302,6 +310,9 @@ void QWindowCompositor::paintChildren(QWaylandSurface *surface, QWaylandSurface void QWindowCompositor::render() { m_window->makeCurrent(); + + cleanupGraphicsResources(); + if (!m_backgroundTexture) m_backgroundTexture = textureFromImage(m_backgroundImage); diff --git a/examples/qwindow-compositor/qwindowcompositor.h b/examples/qwindow-compositor/qwindowcompositor.h index d09ffa89..c58c0d57 100644 --- a/examples/qwindow-compositor/qwindowcompositor.h +++ b/examples/qwindow-compositor/qwindowcompositor.h @@ -72,7 +72,7 @@ protected: QWaylandSurface* surfaceAt(const QPointF &point, QPointF *local = 0); GLuint composeSurface(QWaylandSurface *surface, bool *textureOwned); - void paintChildren(QWaylandSurface *surface, QWaylandSurface *window); + void paintChildren(QWaylandSurface *surface, QWaylandSurface *window, const QSize &windowSize); bool eventFilter(QObject *obj, QEvent *event); |