From cdb8ca28a820338ffc4e86f7d6adb17ea232f0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Tue, 14 Feb 2012 21:03:47 +0100 Subject: Refactor wlsurface, MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/compositor/wayland_wrapper/wlsurface.cpp | 250 +++++++++++---------- src/compositor/wayland_wrapper/wlsurface.h | 19 +- src/compositor/wayland_wrapper/wlsurfacebuffer.cpp | 55 +++-- src/compositor/wayland_wrapper/wlsurfacebuffer.h | 35 ++- 4 files changed, 187 insertions(+), 172 deletions(-) diff --git a/src/compositor/wayland_wrapper/wlsurface.cpp b/src/compositor/wayland_wrapper/wlsurface.cpp index aa2bfb306..0b17e6010 100644 --- a/src/compositor/wayland_wrapper/wlsurface.cpp +++ b/src/compositor/wayland_wrapper/wlsurface.cpp @@ -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(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(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(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)->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 = { diff --git a/src/compositor/wayland_wrapper/wlsurface.h b/src/compositor/wayland_wrapper/wlsurface.h index 99476c826..b79691662 100644 --- a/src/compositor/wayland_wrapper/wlsurface.h +++ b/src/compositor/wayland_wrapper/wlsurface.h @@ -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 m_bufferQueue; + SurfaceBuffer *m_backBuffer; + SurfaceBuffer *m_frontBuffer; + QList 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 diff --git a/src/compositor/wayland_wrapper/wlsurfacebuffer.cpp b/src/compositor/wayland_wrapper/wlsurfacebuffer.cpp index 240c58c37..0a3527993 100644 --- a/src/compositor/wayland_wrapper/wlsurfacebuffer.cpp +++ b/src/compositor/wayland_wrapper/wlsurfacebuffer.cpp @@ -40,14 +40,19 @@ #include "wlsurfacebuffer.h" +#ifdef QT_COMPOSITOR_WAYLAND_GL +#include "hardware_integration/graphicshardwareintegration.h" +#include +#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(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 } } diff --git a/src/compositor/wayland_wrapper/wlsurfacebuffer.h b/src/compositor/wayland_wrapper/wlsurfacebuffer.h index 00f19371a..33a248ff8 100644 --- a/src/compositor/wayland_wrapper/wlsurfacebuffer.h +++ b/src/compositor/wayland_wrapper/wlsurfacebuffer.h @@ -46,6 +46,9 @@ #include +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; -- cgit v1.2.3