Avoid flicker when switching back to composited mode
authorPaul Olav Tvete <paul.tvete@nokia.com>
Fri, 2 Mar 2012 09:12:29 +0000 (10:12 +0100)
committerAndy Nichols <andy.nichols@nokia.com>
Fri, 2 Mar 2012 11:39:52 +0000 (12:39 +0100)
The surface item needs to create a new texture when the compositor
switches from direct render to composited mode.

Change-Id: Ic2d65929617f1941ea290645ac28b8e986c414bc
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
src/compositor/compositor_api/waylandsurfaceitem.cpp
src/compositor/compositor_api/waylandsurfaceitem.h
src/compositor/wayland_wrapper/wlsurface.cpp

index 471e5ca..aff24cd 100644 (file)
@@ -248,6 +248,12 @@ void WaylandSurfaceItem::surfaceDestroyed(QObject *)
     m_surface = 0;
 }
 
+void WaylandSurfaceItem::setDamagedFlag(bool on)
+{
+    m_damaged = on;
+}
+
+
 void WaylandSurfaceItem::surfaceDamaged(const QRect &)
 {
     m_damaged = true;
@@ -298,13 +304,23 @@ void WaylandSurfaceItem::setPaintEnabled(bool enabled)
     update();
 }
 
-QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+class WaylandSurfaceNode : public QSGSimpleTextureNode
 {
-    if (!m_surface) {
-        delete oldNode;
-        return 0;
+public:
+    WaylandSurfaceNode(WaylandSurfaceItem *item) : m_item(item) {
+        setFlag(UsePreprocess,true);
+    }
+    void preprocess() {
+        if (m_item->m_damaged)
+            m_item->updateNodeTexture(this);
     }
+private:
+    WaylandSurfaceItem *m_item;
+};
+
 
+void WaylandSurfaceItem::updateNodeTexture(WaylandSurfaceNode *node)
+{
     if (m_damaged) {
         QSGTexture *oldTexture = m_texture;
         if (m_surface->type() == WaylandSurface::Texture) {
@@ -327,25 +343,32 @@ QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
         m_provider->smooth = smooth();
     }
 
-    QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode);
-    if (!m_texture || !m_paintEnabled) {
+    node->setTexture(m_texture);
+    node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
+}
+
+
+QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+    if (!m_surface || !m_paintEnabled) {
         delete oldNode;
         return 0;
     }
 
+    WaylandSurfaceNode *node = static_cast<WaylandSurfaceNode *>(oldNode);
+
     if (!node) {
-        node = new QSGSimpleTextureNode();
+        node = new WaylandSurfaceNode(this);
     }
 
+    updateNodeTexture(node);
+
     if (surface()->isYInverted()) {
         node->setRect(0, height(), width(), -height());
     } else {
         node->setRect(0, 0, width(), height());
     }
 
-    node->setTexture(m_texture);
-    node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
-
     return node;
 }
 
index 0114f12..b59ce8e 100644 (file)
@@ -50,6 +50,7 @@
 #include <QtQuick/qsgtextureprovider.h>
 
 class WaylandSurfaceTextureProvider;
+class WaylandSurfaceNode;
 
 Q_DECLARE_METATYPE(WaylandSurface*)
 
@@ -85,6 +86,8 @@ public:
     void setClientRenderingEnabled(bool enabled);
     void setTouchEventsEnabled(bool enabled);
 
+    void setDamagedFlag(bool on);
+
 protected:
     void mousePressEvent(QMouseEvent *event);
     void mouseMoveEvent(QMouseEvent *event);
@@ -120,6 +123,8 @@ protected:
     QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
 
 private:
+    friend class WaylandSurfaceNode;
+    void updateNodeTexture(WaylandSurfaceNode *newNode);
     QPoint toSurface(const QPointF &pos) const;
     void init(WaylandSurface *);
 
index 7aa7516..92ee0e7 100644 (file)
@@ -41,6 +41,7 @@
 #include "wlsurface.h"
 
 #include "waylandsurface.h"
+#include "waylandsurfaceitem.h"
 
 #include "wlcompositor.h"
 #include "wlshmbuffer.h"
@@ -319,6 +320,9 @@ bool Surface::advanceBufferQueue()
 
 void Surface::doUpdate() {
     if (postBuffer()) {
+        WaylandSurfaceItem *surfaceItem = waylandSurface()->surfaceItem();
+        if (surfaceItem)
+            surfaceItem->setDamagedFlag(true); // avoid flicker when we switch back to composited mode
         sendFrameCallback();
     } else {
         SurfaceBuffer *surfaceBuffer = currentSurfaceBuffer();