summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@jollamobile.com>2014-01-18 07:40:21 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-21 14:09:18 +0100
commit36ff0f303b79dcd7aae93d5a73dfc1f179ac5560 (patch)
tree786453094160454edd96020901ef63a9bf9a0905 /examples
parentbbf7285b669b105c7ccb6629d963b5e2584453d8 (diff)
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.cpp13
-rw-r--r--examples/qwindow-compositor/qwindowcompositor.cpp23
-rw-r--r--examples/qwindow-compositor/qwindowcompositor.h2
3 files changed, 27 insertions, 11 deletions
diff --git a/examples/qwidget-compositor/main.cpp b/examples/qwidget-compositor/main.cpp
index 2c58fe98d..1badb06ac 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 79d5b111b..19f7ce5ec 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 d09ffa893..c58c0d571 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);