Refactor wlsurface,
authorJørgen Lind <jorgen.lind@nokia.com>
Tue, 14 Feb 2012 20:03:47 +0000 (21:03 +0100)
committerSamuel Rødal <samuel.rodal@nokia.com>
Wed, 29 Feb 2012 15:28:53 +0000 (16:28 +0100)
Now we treat all buffers the same (shm or not).
We advance the queue when we send the frame signal

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

index aa2bfb3..0b17e60 100644 (file)
@@ -76,8 +76,8 @@ void destroy_surface(struct wl_resource *resource)
 Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor)
     : m_compositor(compositor)
     , m_waylandSurface(new WaylandSurface(this))
-    , m_surfaceBuffer(0)
-    , m_textureBuffer(0)
+    , m_backBuffer(0)
+    , m_frontBuffer(0)
     , m_surfaceMapped(false)
     , m_extendedSurface(0)
     , m_subSurface(0)
@@ -98,10 +98,11 @@ Surface::~Surface()
 
 WaylandSurface::Type Surface::type() const
 {
-    if (m_surfaceBuffer && m_surfaceBuffer->handle()) {
-        if (m_surfaceBuffer && m_surfaceBuffer->isShmBuffer()) {
+    SurfaceBuffer *surfaceBuffer = currentSurfaceBuffer();
+    if (surfaceBuffer && surfaceBuffer->handle()) {
+        if (surfaceBuffer->isShmBuffer()) {
             return WaylandSurface::Shm;
-        } else if (m_surfaceBuffer){
+        } else {
             return WaylandSurface::Texture;
         }
     }
@@ -112,12 +113,14 @@ bool Surface::isYInverted() const
 {
     bool ret = false;
     static bool negateReturn = qgetenv("QT_COMPOSITOR_NEGATE_INVERTED_Y").toInt();
+    GraphicsHardwareIntegration *graphicsHWIntegration = m_compositor->graphicsHWIntegration();
 
 #ifdef QT_COMPOSITOR_WAYLAND_GL
-    if (!m_surfaceBuffer) {
+    SurfaceBuffer *surfacebuffer = currentSurfaceBuffer();
+    if (!surfacebuffer) {
         ret = false;
-    } else if (m_compositor->graphicsHWIntegration() && m_surfaceBuffer->handle() && type() != WaylandSurface::Shm) {
-        ret = m_compositor->graphicsHWIntegration()->isYInverted(m_surfaceBuffer->handle());
+    } else if (graphicsHWIntegration && surfacebuffer->handle() && type() != WaylandSurface::Shm) {
+        ret = graphicsHWIntegration->isYInverted(surfacebuffer->handle());
     } else
 #endif
         ret = true;
@@ -127,17 +130,9 @@ bool Surface::isYInverted() const
 
 bool Surface::visible() const
 {
-    return m_surfaceBuffer && m_surfaceBuffer->handle();
-}
 
-QImage Surface::image() const
-{
-    if (type() == WaylandSurface::Shm && m_surfaceBuffer && m_surfaceBuffer->handle()) {
-        ShmBuffer *shmBuffer = static_cast<ShmBuffer *>(m_surfaceBuffer->handle()->user_data);
-        //TODO SHM: m_surfaceBuffer->bufferHandled = true;
-        return shmBuffer->image();
-    }
-    return QImage();
+    SurfaceBuffer *surfacebuffer = currentSurfaceBuffer();
+    return surfacebuffer->handle();
 }
 
 QPointF Surface::pos() const
@@ -166,28 +161,59 @@ void Surface::setSize(const QSize &size)
         m_waylandSurface->sizeChanged();
 }
 
+QImage Surface::image() const
+{
+    SurfaceBuffer *surfacebuffer = currentSurfaceBuffer();
+    if (surfacebuffer && !surfacebuffer->bufferIsDestroyed() && type() == WaylandSurface::Shm) {
+        ShmBuffer *shmBuffer = static_cast<ShmBuffer *>(surfacebuffer->handle()->user_data);
+        return shmBuffer->image();
+    }
+    return QImage();
+}
+
 #ifdef QT_COMPOSITOR_WAYLAND_GL
 GLuint Surface::textureId(QOpenGLContext *context) const
 {
-    if (!m_surfaceBuffer) {
-        return 0;
-    }
-    if (m_compositor->graphicsHWIntegration() && type() == WaylandSurface::Texture
-         && !m_surfaceBuffer->textureCreated()) {
-        Surface *that = const_cast<Surface *>(this);
+    const SurfaceBuffer *surfacebuffer = currentSurfaceBuffer();
 
-        if (m_textureBuffer) {
-            m_textureBuffer->destructBufferState();
-            that->m_textureBuffer = 0;
-        }
+    if (m_compositor->graphicsHWIntegration() && type() == WaylandSurface::Texture
+         && !surfacebuffer->textureCreated()) {
         GraphicsHardwareIntegration *hwIntegration = m_compositor->graphicsHWIntegration();
-        that->m_textureBuffer = m_surfaceBuffer;
-        that->m_textureBuffer->setTexture(hwIntegration->createTextureFromBuffer(m_textureBuffer->handle(), context));
+        const_cast<SurfaceBuffer *>(surfacebuffer)->createTexture(hwIntegration,context);
     }
-    return m_textureBuffer->texture();
+    return surfacebuffer->texture();
 }
 #endif // QT_COMPOSITOR_WAYLAND_GL
 
+void Surface::sendFrameCallback()
+{
+    SurfaceBuffer *surfacebuffer = currentSurfaceBuffer();
+    surfacebuffer->setDisplayed();
+    if (m_backBuffer) {
+        if (m_frontBuffer)
+            m_frontBuffer->destructBufferState();
+        m_frontBuffer = m_backBuffer;
+    }
+
+    advanceBufferQueue();
+
+    uint time = Compositor::currentTimeMsecs();
+    struct wl_resource *frame_callback;
+    wl_list_for_each(frame_callback, &m_frame_callback_list, link) {
+        wl_resource_post_event(frame_callback,WL_CALLBACK_DONE,time);
+        wl_resource_destroy(frame_callback,Compositor::currentTimeMsecs());
+    }
+
+    wl_list_init(&m_frame_callback_list);
+
+    doUpdate();
+}
+
+void Surface::frameFinished()
+{
+    m_compositor->frameFinished(this);
+}
+
 WaylandSurface * Surface::waylandSurface() const
 {
     return m_waylandSurface;
@@ -233,68 +259,66 @@ Compositor *Surface::compositor() const
     return m_compositor;
 }
 
-void Surface::sendFrameCallback()
+void Surface::advanceBufferQueue()
 {
-    frameFinishedInternal();
-
-    uint time = Compositor::currentTimeMsecs();
-    struct wl_resource *frame_callback;
-    wl_list_for_each(frame_callback, &m_frame_callback_list, link) {
-        wl_resource_post_event(frame_callback,WL_CALLBACK_DONE,time);
-        wl_resource_destroy(frame_callback,Compositor::currentTimeMsecs());
-    }
+    //has current buffer been displayed,
+    //do we have another buffer in the queue
+    //and does it have a valid damage rect
+
+    if (m_bufferQueue.size()) {
+        int width = 0;
+        int height = 0;
+        if (m_backBuffer) {
+            width = m_backBuffer->width();
+            height = m_backBuffer->height();
+        }
 
-    wl_list_init(&m_frame_callback_list);
-}
+        m_backBuffer = m_bufferQueue.takeFirst();
+        while (m_backBuffer && m_backBuffer->bufferIsDestroyed()) {
+            m_backBuffer->destructBufferState();
+            m_bufferQueue.takeFirst();
+            m_backBuffer = m_bufferQueue.size() ? m_bufferQueue.first():0;
+        }
 
-void Surface::frameFinished()
-{
-    m_compositor->frameFinished(this);
-}
+        if (!m_backBuffer)
+            return; //we have no new backbuffer;
 
-void Surface::doUpdate(const QRect &rect) {
-    if (postBuffer()) {
-        m_surfaceBuffer->setPosted();  // disown buffer....
-        if (m_textureBuffer) {
-            m_textureBuffer->destructBufferState();
-            m_textureBuffer = 0;
+        if (m_backBuffer->handle()) {
+            if (width != m_backBuffer->width() ||
+                    height != m_backBuffer->height()) {
+                width = m_backBuffer->width();
+                height = m_backBuffer->height();
+            }
         }
-        if (!m_bufferQueue.isEmpty()) {
-            qDebug() << "++++++++++++++++++++++++++++++++++++++++ recursive damage :-)";
-            newCurrentBuffer();
-            doUpdate(rect);
+        setSize(QSize(width,height));
+
+
+        if (m_backBuffer &&  (!m_subSurface || !m_subSurface->parent()) && !m_surfaceMapped) {
+            m_surfaceMapped = true;
+            emit m_waylandSurface->mapped();
+        } else if (!m_backBuffer->handle() && m_surfaceMapped) {
+            m_surfaceMapped = false;
+            emit m_waylandSurface->unmapped();
         }
+
     } else {
-        m_compositor->markSurfaceAsDirty(this);
-        emit m_waylandSurface->damaged(rect);
+        m_backBuffer = 0;
     }
-}
 
-void Surface::newCurrentBuffer() {
-    //TODO release SHM buffer....
-    if (m_surfaceBuffer && m_surfaceBuffer->isPosted()) {
-        m_surfaceBuffer->destructBufferState();
-    } else if (m_surfaceBuffer && !m_surfaceBuffer->isDisplayed()) {
-        qDebug() << "### not skipping undisplayed buffer";
-        return;
-    }
 
-    m_surfaceBuffer = m_bufferQueue.takeFirst();
+}
 
-    int width = 0;
-    int height = 0;
-    if (m_surfaceBuffer) {
-        width = m_surfaceBuffer->width();
-        height = m_surfaceBuffer->height();
-    }
-    setSize(QSize(width,height));
-
-    if (m_surfaceBuffer &&  (!m_subSurface || !m_subSurface->parent()) && !m_surfaceMapped) {
-        emit m_waylandSurface->mapped();
-        m_surfaceMapped = true;
-    } else if (!m_surfaceBuffer && m_surfaceMapped) {
-        emit m_waylandSurface->unmapped();
-        m_surfaceMapped = false;
+void Surface::doUpdate() {
+    if (postBuffer()) {
+        sendFrameCallback();
+    } else {
+        SurfaceBuffer *surfaceBuffer = currentSurfaceBuffer();
+        if (surfaceBuffer) {
+            if (surfaceBuffer->damageRect().isValid()) {
+                m_compositor->markSurfaceAsDirty(this);
+                emit m_waylandSurface->damaged(surfaceBuffer->damageRect());
+            }
+        }
     }
 }
 
@@ -313,22 +337,11 @@ SurfaceBuffer *Surface::createSurfaceBuffer(struct wl_buffer *buffer)
     return newBuffer;
 }
 
-void Surface::frameFinishedInternal() {
-    if (m_surfaceBuffer)
-        m_surfaceBuffer->setFinished();
-
-    if (!m_bufferQueue.isEmpty()) {
-        newCurrentBuffer();
-        if (m_surfaceBuffer)
-            doUpdate(m_surfaceBuffer->damageRect());
-    }
-}
-
 bool Surface::postBuffer() {
 #ifdef QT_COMPOSITOR_WAYLAND_GL
     if (m_compositor->graphicsHWIntegration() && m_waylandSurface->handle() == m_compositor->directRenderSurface()) {
-        //            qDebug() << "posting...." << bufferQueue;
-        if (m_surfaceBuffer && m_surfaceBuffer->handle() && m_compositor->graphicsHWIntegration()->postBuffer(m_surfaceBuffer->handle())) {
+        SurfaceBuffer *surfaceBuffer = m_backBuffer? m_backBuffer : m_frontBuffer;
+        if (surfaceBuffer && m_compositor->graphicsHWIntegration()->postBuffer(surfaceBuffer->handle())) {
             return true;
         } else {
             qDebug() << "could not post buffer";
@@ -340,45 +353,34 @@ bool Surface::postBuffer() {
 
 void Surface::attach(struct wl_buffer *buffer)
 {
-    static bool no_serverside_buffer_queue = qgetenv("QT_NO_SERVERSIDE_BUFFER_QUEUE").toInt();
-
-    SurfaceBuffer *newBuffer = 0;
-    if (no_serverside_buffer_queue) {
-        if (m_surfaceBuffer && !m_surfaceBuffer->textureCreated()) {
-            qDebug() << "releasing undisplayed buffer";
-            m_surfaceBuffer->destructBufferState();
-            m_surfaceBuffer = 0;
+    SurfaceBuffer *last = m_bufferQueue.size()?m_bufferQueue.last():0;
+    if (last) {
+        if (last->handle() == buffer)
+            return;
+        if (!last->damageRect().isValid()) {
+            last->destructBufferState();
+            m_bufferQueue.takeLast();
         }
     }
-    if (buffer) {
-        newBuffer = createSurfaceBuffer(buffer);
-    }
 
-    SurfaceBuffer *last = m_bufferQueue.size()?m_bufferQueue.last():0;
-    if (last && !last->damageRect().isValid()) {
-        last->destructBufferState();
-        m_bufferQueue.takeLast();
-    }
-    m_bufferQueue << newBuffer;
+    m_bufferQueue <<  createSurfaceBuffer(buffer);
 }
 
 void Surface::damage(const QRect &rect)
 {
-    if (!m_bufferQueue.isEmpty() && (!m_surfaceBuffer || m_surfaceBuffer->isFinished() || !m_surfaceBuffer->handle())) {
-            // Handle the "slow" case where we've finished the previous frame before the next damage comes.
-            newCurrentBuffer();
-            doUpdate(rect);
-    } else if (m_bufferQueue.isEmpty()) {
-        // we've receicved a second damage for the same buffer
-        doUpdate(rect);
-    } else {
-        // we're still composing the previous buffer, so just store the damage rect for later
-        SurfaceBuffer *b = m_bufferQueue.last();
-        if (b)
-            b->setDamage(rect);
+    if (m_bufferQueue.size()) {
+        SurfaceBuffer *surfaceBuffer = m_bufferQueue.last();
+        if (surfaceBuffer)
+            surfaceBuffer->setDamage(rect);
         else
             qWarning() << "Surface::damage() null buffer";
+        if (!m_backBuffer)
+            advanceBufferQueue();
+    } else {
+        // we've receicved a second damage for the same buffer
+        currentSurfaceBuffer()->setDamage(rect);
     }
+    doUpdate();
 }
 
 const struct wl_surface_interface Surface::surface_interface = {
index 99476c8..b796916 100644 (file)
@@ -85,14 +85,14 @@ public:
 
     uint id() const { return base()->resource.object.id; }
 
-    QImage image() const;
-
     QPointF pos() const;
     void setPos(const QPointF  &pos);
 
     QSize size() const;
     void setSize(const QSize &size);
 
+    QImage image() const;
+
 #ifdef QT_COMPOSITOR_WAYLAND_GL
     GLuint textureId(QOpenGLContext *context) const;
 #endif
@@ -124,9 +124,9 @@ private:
     Compositor *m_compositor;
     WaylandSurface *m_waylandSurface;
 
-    SurfaceBuffer  *m_surfaceBuffer;
-    SurfaceBuffer *m_textureBuffer;
-    QList<SurfaceBuffer*> m_bufferQueue;
+    SurfaceBuffer *m_backBuffer;
+    SurfaceBuffer *m_frontBuffer;
+    QList<SurfaceBuffer *> m_bufferQueue;
     bool m_surfaceMapped;
 
     QPoint m_lastLocalMousePos;
@@ -144,8 +144,9 @@ private:
     QPointF m_position;
     QSize m_size;
 
-    void doUpdate(const QRect &rect);
-    void newCurrentBuffer();
+    inline SurfaceBuffer *currentSurfaceBuffer() const;
+    void advanceBufferQueue();
+    void doUpdate();
     SurfaceBuffer *createSurfaceBuffer(struct wl_buffer *buffer);
     void frameFinishedInternal();
     bool postBuffer();
@@ -163,6 +164,10 @@ private:
 
 };
 
+inline SurfaceBuffer *Surface::currentSurfaceBuffer() const {
+    return m_backBuffer? m_backBuffer : m_frontBuffer;
+}
+
 }
 
 #endif //WL_SURFACE_H
index 240c58c..0a35279 100644 (file)
 
 #include "wlsurfacebuffer.h"
 
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+#include "hardware_integration/graphicshardwareintegration.h"
+#include <QtGui/QPlatformOpenGLContext>
+#endif
+
 namespace Wayland {
 
 SurfaceBuffer::SurfaceBuffer()
     : m_buffer(0)
-    , m_is_released_sent(false)
+    , m_dont_send_release(false)
     , m_is_registered_for_buffer(false)
-    , m_is_posted(false)
-    , m_is_frame_finished(false)
+    , m_is_displayed(false)
+    , m_is_destroyed(false)
     , m_texture(0)
 {
 }
@@ -62,13 +67,14 @@ void SurfaceBuffer::initialize(wl_buffer *buffer)
 {
     m_buffer = buffer;
     m_texture = 0;
-    m_is_released_sent = false;
+    m_dont_send_release = false;
     m_is_registered_for_buffer = true;
-    m_is_posted = false;
-    m_is_frame_finished = false;
+    m_is_displayed = false;
+    m_is_destroyed = false;
     m_destroy_listener.surfaceBuffer = this;
     m_destroy_listener.listener.func = destroy_listener_callback;
-    wl_list_insert(&buffer->resource.destroy_listener_list,&m_destroy_listener.listener.link);
+    if (buffer)
+        wl_list_insert(&buffer->resource.destroy_listener_list,&m_destroy_listener.listener.link);
     m_damageRect = QRect();
 }
 
@@ -81,29 +87,35 @@ void SurfaceBuffer::destructBufferState()
     }
     m_buffer = 0;
     m_is_registered_for_buffer = false;
-    m_is_posted = 0;
+    m_is_displayed = false;
 }
 
 void SurfaceBuffer::sendRelease()
 {
     Q_ASSERT(m_buffer);
+    if (m_dont_send_release)
+        return;
     wl_resource_post_event(&m_buffer->resource, WL_BUFFER_RELEASE);
-    m_buffer = 0;
-    m_is_released_sent = true;
+    m_dont_send_release = true;
 }
 
-void SurfaceBuffer::setPosted()
+void SurfaceBuffer::dontSendRelease()
 {
-    m_is_posted = true;
-     if (m_buffer) {
-        wl_list_remove(&m_destroy_listener.listener.link);
-     }
-     m_buffer = 0;
+    m_dont_send_release = true;
+}
+
+void SurfaceBuffer::setDisplayed()
+{
+    m_is_displayed = true;
+    m_damageRect = QRect();
 }
 
-void SurfaceBuffer::setFinished()
+void SurfaceBuffer::setDamage(const QRect &rect)
 {
-    m_is_frame_finished = true;
+        if (m_damageRect.isValid()) {
+        m_damageRect = m_damageRect.united(rect);
+    }
+    m_damageRect = rect;
 }
 
 void SurfaceBuffer::destroyTexture()
@@ -124,12 +136,15 @@ void SurfaceBuffer::destroy_listener_callback(wl_listener *listener, wl_resource
                 reinterpret_cast<struct surface_buffer_destroy_listener *>(listener);
         SurfaceBuffer *d = destroy_listener->surfaceBuffer;
         d->destroyTexture();
+        d->m_is_destroyed = true;
         d->m_buffer = 0;
 }
 
-void SurfaceBuffer::setTexture(GLuint texId)
+void SurfaceBuffer::createTexture(GraphicsHardwareIntegration *hwIntegration, QOpenGLContext *context)
 {
-    m_texture = texId;
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+    m_texture = hwIntegration->createTextureFromBuffer(m_buffer, context);
+#endif
 }
 
 }
index 00f1937..33a248f 100644 (file)
@@ -46,6 +46,9 @@
 
 #include <wayland-server.h>
 
+class GraphicsHardwareIntegration;
+class QOpenGLContext;
+
 namespace Wayland {
 
 struct surface_buffer_destroy_listener
@@ -65,39 +68,29 @@ public:
 
     void initialize(struct wl_buffer *buffer);
     void destructBufferState();
-    inline bool bufferIsDestroyed() const { return m_is_registered_for_buffer &&!m_buffer; }
+    inline bool bufferIsDestroyed() const { return m_is_destroyed; }
 
     inline int32_t width() const { return m_buffer->width; }
     inline int32_t height() const { return m_buffer->height; }
 
     inline bool isShmBuffer() const { return wl_buffer_is_shm(m_buffer); }
 
-    inline bool isReleasedSent() const { return m_is_released_sent; }
     inline bool isRegisteredWithBuffer() const { return m_is_registered_for_buffer; }
 
     void sendRelease();
+    void dontSendRelease();
 
-    void setPosted();
-
-    void setFinished();
-
-    inline bool isPosted() const { return m_is_posted; }
+    void setDisplayed();
 
-    //this is wrong. Should have a frameSent function;
-    inline bool isDisplayed() const { return m_texture || m_is_posted || wl_buffer_is_shm(m_buffer); }
-
-    //I don't know understand isFinished.
-    inline bool isFinished() const { return m_is_frame_finished; }
+    inline bool isDisplayed() const { return m_is_displayed; }
 
     inline QRect damageRect() const { return m_damageRect; }
-
-    inline void setDamage(const QRect &rect) { m_damageRect = rect; }
+    void setDamage(const QRect &rect);
 
     inline bool textureCreated() const { return m_texture; }
 
-    void setTexture(GLuint texId);
-    inline GLuint texture();
-
+    void createTexture(GraphicsHardwareIntegration *hwIntegration, QOpenGLContext *context);
+    inline GLuint texture() const;
     void destroyTexture();
 
     inline struct wl_buffer *handle() const { return m_buffer; }
@@ -105,10 +98,10 @@ private:
     struct wl_buffer *m_buffer;
     struct surface_buffer_destroy_listener m_destroy_listener;
     QRect m_damageRect;
-    bool m_is_released_sent;
+    bool m_dont_send_release;
     bool m_is_registered_for_buffer;
-    bool m_is_posted;
-    bool m_is_frame_finished;
+    bool m_is_displayed;
+    bool m_is_destroyed;
 #ifdef QT_COMPOSITOR_WAYLAND_GL
     GLuint m_texture;
 #else
@@ -120,7 +113,7 @@ private:
 
 };
 
-GLuint SurfaceBuffer::texture()
+GLuint SurfaceBuffer::texture() const
 {
     if (m_buffer)
         return m_texture;