diff options
Diffstat (limited to 'src/compositor/wayland_wrapper/wlsurface.cpp')
-rw-r--r-- | src/compositor/wayland_wrapper/wlsurface.cpp | 711 |
1 files changed, 209 insertions, 502 deletions
diff --git a/src/compositor/wayland_wrapper/wlsurface.cpp b/src/compositor/wayland_wrapper/wlsurface.cpp index d516e1db5..72cc45ad9 100644 --- a/src/compositor/wayland_wrapper/wlsurface.cpp +++ b/src/compositor/wayland_wrapper/wlsurface.cpp @@ -47,16 +47,13 @@ #include "wlinputdevice.h" #include "wlextendedsurface.h" #include "wlsubsurface.h" +#include "wlsurfacebuffer.h" #include <QtCore/QDebug> #include <QTouchEvent> #include <wayland-server.h> -#ifdef Q_OS_LINUX -#include <linux/input.h> -#endif - #ifdef QT_COMPOSITOR_WAYLAND_GL #include "hardware_integration/graphicshardwareintegration.h" #include <QtGui/QPlatformOpenGLContext> @@ -68,358 +65,39 @@ namespace Wayland { -static const int buffer_pool_size = 3; - -struct surface_buffer_destroy_listener -{ - struct wl_listener listener; - class SurfaceBuffer *surfaceBuffer; -}; - - -class SurfaceBuffer -{ -public: - SurfaceBuffer() - : m_buffer(0) - , m_is_released_sent(false) - , m_is_registered_for_buffer(false) - , m_is_posted(false) - , m_is_frame_finished(false) - , m_texture(0) - { - } - - ~SurfaceBuffer() - { - if (m_is_registered_for_buffer) - destructBufferState(); - } - - void initialize(struct wl_buffer *buffer) - { - m_buffer = buffer; - m_texture = 0; - m_is_released_sent = false; - m_is_registered_for_buffer = true; - m_is_posted = false; - m_is_frame_finished = 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); - m_damageRect = QRect(); - } - - void destructBufferState() - { - destroyTexture(); - if (m_buffer) { - wl_list_remove(&m_destroy_listener.listener.link); - sendRelease(); - } - m_buffer = 0; - m_is_registered_for_buffer = false; - m_is_posted = 0; - } - - inline int32_t width() const { return m_buffer->width; } - inline int32_t height() const { return m_buffer->height; } - - - inline bool bufferIsDestroyed() const { return m_is_registered_for_buffer &&!m_buffer; } - 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() - { - Q_ASSERT(m_buffer); - wl_resource_post_event(&m_buffer->resource, WL_BUFFER_RELEASE); - m_buffer = 0; - m_is_released_sent = true; - } - - void setPosted() { - m_is_posted = true; - if (m_buffer) { - wl_list_remove(&m_destroy_listener.listener.link); - } - m_buffer = 0; - } - - void setFinished() { m_is_frame_finished = true; } - - inline bool isPosted() const { return m_is_posted; } - inline bool isDisplayed() const { return m_texture || m_is_posted || wl_buffer_is_shm(m_buffer); } - inline bool isFinished() const { return m_is_frame_finished; } - - inline QRect damageRect() const { return m_damageRect; } - - inline void setDamage(const QRect &rect) { m_damageRect = rect; } - - inline bool textureCreated() const - { - return m_texture; - } - - inline GLuint texture() - { - if (m_buffer) - return m_texture; - return 0; - } - - inline void setTexture(GLuint texId) - { - m_texture = texId; - } - - inline void destroyTexture() - { -#ifdef QT_COMPOSITOR_WAYLAND_GL - if (m_texture) { - glDeleteTextures(1,&m_texture); - m_texture = 0; - } -#endif - } - - inline struct wl_buffer *handle() const { return m_buffer; } -private: - struct wl_buffer *m_buffer; - struct surface_buffer_destroy_listener m_destroy_listener; - QRect m_damageRect; - bool m_is_released_sent; - bool m_is_registered_for_buffer; - bool m_is_posted; - bool m_is_frame_finished; -#ifdef QT_COMPOSITOR_WAYLAND_GL - GLuint m_texture; -#else - uint m_texture; -#endif - - static void destroy_listener_callback(struct wl_listener *listener, - struct wl_resource *resource, uint32_t time) - { - Q_UNUSED(resource); - Q_UNUSED(time); - struct surface_buffer_destroy_listener *destroy_listener = - reinterpret_cast<struct surface_buffer_destroy_listener *>(listener); - SurfaceBuffer *d = destroy_listener->surfaceBuffer; - d->destroyTexture(); - d->m_buffer = 0; - } -}; - - -const struct wl_surface_interface Surface::surface_interface = { - Surface::surface_destroy, - Surface::surface_attach, - Surface::surface_damage, - Surface::surface_frame -}; - -class SurfacePrivate -{ - Q_DECLARE_PUBLIC(Surface) -public: - SurfacePrivate(Surface *surface, Compositor *compositor) - : compositor(compositor) - , qtSurface(new WaylandSurface(surface)) - , surfaceBuffer(0) - , textureBuffer(0) - , surfaceMapped(false) - , processId(0) - , extendedSurface(0) - , subSurface(0) - , shellSurface(0) - , q_ptr(surface) - - { - wl_list_init(&frame_callback_list); - } - - static void destroy_frame_callback(struct wl_resource *resource) - { - delete resource; - } - - void doUpdate(const QRect &rect) { - if (postBuffer()) { - surfaceBuffer->setPosted(); // disown buffer.... - if (textureBuffer) { - textureBuffer->destructBufferState(); - textureBuffer = 0; - } - if (!bufferQueue.isEmpty()) { - qDebug() << "++++++++++++++++++++++++++++++++++++++++ recursive damage :-)"; - newCurrentBuffer(); - doUpdate(rect); - } - } else { - compositor->markSurfaceAsDirty(q_ptr); - emit qtSurface->damaged(rect); - } - } - - void newCurrentBuffer() { - //TODO release SHM buffer.... - if (surfaceBuffer && surfaceBuffer->isPosted()) { - surfaceBuffer->destructBufferState(); - } else if (surfaceBuffer && !surfaceBuffer->isDisplayed()) { - qDebug() << "### not skipping undisplayed buffer"; - return; - } - - surfaceBuffer = bufferQueue.takeFirst(); - - int width = 0; - int height = 0; - if (surfaceBuffer) { - width = surfaceBuffer->width(); - height = surfaceBuffer->height(); - } - q_ptr->setSize(QSize(width,height)); - - if (surfaceBuffer && (!subSurface || !subSurface->parent()) && !surfaceMapped) { - emit qtSurface->mapped(); - surfaceMapped = true; - } else if (!surfaceBuffer && surfaceMapped) { - emit qtSurface->unmapped(); - surfaceMapped = false; - } - } - - SurfaceBuffer *createSurfaceBuffer(struct wl_buffer *buffer) - { - SurfaceBuffer *newBuffer = 0; - for (int i = 0; i < buffer_pool_size; i++) { - if (!bufferPool[i].isRegisteredWithBuffer()) { - newBuffer = &bufferPool[i]; - newBuffer->initialize(buffer); - break; - } - } - - Q_ASSERT(newBuffer); - return newBuffer; - } - - void frameFinished() { - if (surfaceBuffer) - surfaceBuffer->setFinished(); - - if (!bufferQueue.isEmpty()) { - newCurrentBuffer(); - if (surfaceBuffer) - doUpdate(surfaceBuffer->damageRect()); - } - } - - bool postBuffer() { -#ifdef QT_COMPOSITOR_WAYLAND_GL - if (compositor->graphicsHWIntegration() && qtSurface->handle() == compositor->directRenderSurface()) { -// qDebug() << "posting...." << bufferQueue; - if (surfaceBuffer && surfaceBuffer->handle() && compositor->graphicsHWIntegration()->postBuffer(surfaceBuffer->handle())) { - return true; - } else { - qDebug() << "could not post buffer"; - } - } -#endif - return false; - } - - Compositor *compositor; - WaylandSurface *qtSurface; - - SurfaceBuffer *surfaceBuffer; - SurfaceBuffer *textureBuffer; - QList<SurfaceBuffer*> bufferQueue; - bool surfaceMapped; - - qint64 processId; - QByteArray authenticationToken; - QVariantMap windowProperties; - - QPoint lastLocalMousePos; - QPoint lastGlobalMousePos; - - struct wl_list frame_callback_list; - - ExtendedSurface *extendedSurface; - SubSurface *subSurface; - ShellSurface *shellSurface; - - SurfaceBuffer bufferPool[buffer_pool_size]; - - QPointF position; - QSize size; - -private: - Surface *q_ptr; -}; - void destroy_surface(struct wl_resource *resource) { Surface *surface = wayland_cast<Surface *>((wl_surface *)resource); delete surface; } -void Surface::surface_destroy(struct wl_client *, struct wl_resource *surface_resource) -{ - wl_resource_destroy(surface_resource,Compositor::currentTimeMsecs()); -} - -void Surface::surface_attach(struct wl_client *client, struct wl_resource *surface, - struct wl_resource *buffer, int x, int y) -{ - Q_UNUSED(client); - Q_UNUSED(x); - Q_UNUSED(y); - reinterpret_cast<Surface *>(surface)->attach(reinterpret_cast<struct wl_buffer *>(buffer)); -} - -void Surface::surface_damage(struct wl_client *client, struct wl_resource *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - Q_UNUSED(client); - reinterpret_cast<Surface *>(surface)->damage(QRect(x, y, width, height)); -} -void Surface::surface_frame(struct wl_client *client, - struct wl_resource *resource, - uint32_t callback) -{ - Surface *surface = reinterpret_cast<Surface *>(resource); - SurfacePrivate *d = surface->d_func(); - struct wl_resource *frame_callback = wl_client_add_object(client,&wl_callback_interface,0,callback,d); - wl_list_insert(&d->frame_callback_list,&frame_callback->link); -} - Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor) - : d_ptr(new SurfacePrivate(this,compositor)) -{ + : m_compositor(compositor) + , m_waylandSurface(new WaylandSurface(this)) + , m_surfaceBuffer(0) + , m_textureBuffer(0) + , m_surfaceMapped(false) + , m_extendedSurface(0) + , m_subSurface(0) + , m_shellSurface(0) +{ + wl_list_init(&m_frame_callback_list); addClientResource(client, &base()->resource, id, &wl_surface_interface, &Surface::surface_interface, destroy_surface); } Surface::~Surface() { - Q_D(Surface); - d->compositor->surfaceDestroyed(this); - - delete d->qtSurface; + m_compositor->surfaceDestroyed(this); + delete m_waylandSurface; } WaylandSurface::Type Surface::type() const { - Q_D(const Surface); - if (d->surfaceBuffer && d->surfaceBuffer->handle()) { - if (d->surfaceBuffer && d->surfaceBuffer->isShmBuffer()) { + if (m_surfaceBuffer && m_surfaceBuffer->handle()) { + if (m_surfaceBuffer && m_surfaceBuffer->isShmBuffer()) { return WaylandSurface::Shm; - } else if (d->surfaceBuffer){ + } else if (m_surfaceBuffer){ return WaylandSurface::Texture; } } @@ -432,12 +110,10 @@ bool Surface::isYInverted() const static bool negateReturn = qgetenv("QT_COMPOSITOR_NEGATE_INVERTED_Y").toInt(); #ifdef QT_COMPOSITOR_WAYLAND_GL - Q_D(const Surface); - - if (!d->surfaceBuffer) { + if (!m_surfaceBuffer) { ret = false; - } else if (d->compositor->graphicsHWIntegration() && d->surfaceBuffer->handle() && type() != WaylandSurface::Shm) { - ret = d->compositor->graphicsHWIntegration()->isYInverted(d->surfaceBuffer->handle()); + } else if (m_compositor->graphicsHWIntegration() && m_surfaceBuffer->handle() && type() != WaylandSurface::Shm) { + ret = m_compositor->graphicsHWIntegration()->isYInverted(m_surfaceBuffer->handle()); } else #endif ret = true; @@ -447,37 +123,14 @@ bool Surface::isYInverted() const bool Surface::visible() const { - Q_D(const Surface); - return d->surfaceBuffer && d->surfaceBuffer->handle(); -} - -void Surface::damage(const QRect &rect) -{ - Q_D(Surface); - - if (!d->bufferQueue.isEmpty() && (!d->surfaceBuffer || d->surfaceBuffer->isFinished() || !d->surfaceBuffer->handle())) { - // Handle the "slow" case where we've finished the previous frame before the next damage comes. - d->newCurrentBuffer(); - d->doUpdate(rect); - } else if (d->bufferQueue.isEmpty()) { - // we've receicved a second damage for the same buffer - d->doUpdate(rect); - } else { - // we're still composing the previous buffer, so just store the damage rect for later - SurfaceBuffer *b = d->bufferQueue.last(); - if (b) - b->setDamage(rect); - else - qWarning() << "Surface::damage() null buffer"; - } + return m_surfaceBuffer && m_surfaceBuffer->handle(); } QImage Surface::image() const { - Q_D(const Surface); - if (type() == WaylandSurface::Shm && d->surfaceBuffer && d->surfaceBuffer->handle()) { - ShmBuffer *shmBuffer = static_cast<ShmBuffer *>(d->surfaceBuffer->handle()->user_data); - //TODO SHM: d->surfaceBuffer->bufferHandled = true; + 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(); @@ -485,225 +138,279 @@ QImage Surface::image() const QPointF Surface::pos() const { - Q_D(const Surface); - return d->position; + return m_position; } void Surface::setPos(const QPointF &pos) { - Q_D(Surface); - bool emitChange = pos != d->position; - d->position = pos; + bool emitChange = pos != m_position; + m_position = pos; if (emitChange) - d->qtSurface->posChanged(); + m_waylandSurface->posChanged(); } QSize Surface::size() const { - Q_D(const Surface); - return d->size; + return m_size; } void Surface::setSize(const QSize &size) { - Q_D(Surface); - bool emitChange = size != d->size; - d->size = size; + bool emitChange = size != m_size; + m_size = size; if (emitChange) - d->qtSurface->sizeChanged(); + m_waylandSurface->sizeChanged(); } #ifdef QT_COMPOSITOR_WAYLAND_GL GLuint Surface::textureId(QOpenGLContext *context) const { - Q_D(const Surface); - - if (!d->surfaceBuffer) { + if (!m_surfaceBuffer) { return 0; } - if (d->compositor->graphicsHWIntegration() && type() == WaylandSurface::Texture - && !d->surfaceBuffer->textureCreated()) { + if (m_compositor->graphicsHWIntegration() && type() == WaylandSurface::Texture + && !m_surfaceBuffer->textureCreated()) { Surface *that = const_cast<Surface *>(this); - if (d->textureBuffer) { - d->textureBuffer->destructBufferState(); - that->d_func()->textureBuffer = 0; + if (m_textureBuffer) { + m_textureBuffer->destructBufferState(); + that->m_textureBuffer = 0; } - GraphicsHardwareIntegration *hwIntegration = d->compositor->graphicsHWIntegration(); - that->d_func()->textureBuffer = d->surfaceBuffer; - that->d_func()->textureBuffer->setTexture(hwIntegration->createTextureFromBuffer(d->textureBuffer->handle(), context)); + GraphicsHardwareIntegration *hwIntegration = m_compositor->graphicsHWIntegration(); + that->m_textureBuffer = m_surfaceBuffer; + that->m_textureBuffer->setTexture(hwIntegration->createTextureFromBuffer(m_textureBuffer->handle(), context)); } - return d->textureBuffer->texture(); + return m_textureBuffer->texture(); } #endif // QT_COMPOSITOR_WAYLAND_GL -void Surface::attach(struct wl_buffer *buffer) +WaylandSurface * Surface::waylandSurface() const { - Q_D(Surface); - static bool no_serverside_buffer_queue = qgetenv("QT_NO_SERVERSIDE_BUFFER_QUEUE").toInt(); - - SurfaceBuffer *newBuffer = 0; - if (no_serverside_buffer_queue) { - if (d->surfaceBuffer && !d->surfaceBuffer->textureCreated()) { - qDebug() << "releasing undisplayed buffer"; - d->surfaceBuffer->destructBufferState(); - d->surfaceBuffer = 0; - } - } - if (buffer) { - newBuffer = d->createSurfaceBuffer(buffer); - } - - SurfaceBuffer *last = d->bufferQueue.size()?d->bufferQueue.last():0; - if (last && !last->damageRect().isValid()) { - last->destructBufferState(); - d->bufferQueue.takeLast(); - } - d->bufferQueue << newBuffer; + return m_waylandSurface; } -WaylandSurface * Surface::handle() const +QPoint Surface::lastMousePos() const { - Q_D(const Surface); - return d->qtSurface; + return m_lastLocalMousePos; } -qint64 Surface::processId() const +void Surface::setExtendedSurface(ExtendedSurface *extendedSurface) { - Q_D(const Surface); - return d->processId; + m_extendedSurface = extendedSurface; } -void Surface::setProcessId(qint64 processId) +ExtendedSurface *Surface::extendedSurface() const { - Q_D(Surface); - d->processId = processId; + return m_extendedSurface; } -QByteArray Surface::authenticationToken() const +void Surface::setSubSurface(SubSurface *subSurface) { - Q_D(const Surface); - WaylandManagedClient *mcl = d->compositor->windowManagerIntegration()->managedClient(base()->resource.client); - return mcl ? mcl->authenticationToken() : QByteArray(); + m_subSurface = subSurface; } -QVariantMap Surface::windowProperties() const +SubSurface *Surface::subSurface() const { - Q_D(const Surface); - return d->windowProperties; + return m_subSurface; } -QVariant Surface::windowProperty(const QString &propertyName) const +void Surface::setShellSurface(ShellSurface *shellSurface) { - Q_D(const Surface); - QVariantMap props = d->windowProperties; - return props.value(propertyName); + m_shellSurface = shellSurface; } -void Surface::setWindowProperty(const QString &name, const QVariant &value, bool writeUpdateToClient) +ShellSurface *Surface::shellSurface() const { - Q_D(Surface); - d->windowProperties.insert(name, value); - handle()->windowPropertyChanged(name,value); - if (writeUpdateToClient && d->extendedSurface) { - d->extendedSurface->sendGenericProperty(name, value); - } + return m_shellSurface; } -Qt::ScreenOrientation Surface::windowOrientation() const +Compositor *Surface::compositor() const { - Q_D(const Surface); - return d->extendedSurface ? d->extendedSurface->windowOrientation() : Qt::PrimaryOrientation; + return m_compositor; } -Qt::ScreenOrientation Surface::contentOrientation() const +void Surface::sendFrameCallback() { - Q_D(const Surface); - return d->extendedSurface ? d->extendedSurface->contentOrientation() : Qt::PrimaryOrientation; + frameFinished(); + + 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); } -WaylandSurface::WindowFlags Surface::windowFlags() const +void Surface::frameFinished() { - Q_D(const Surface); - return d->extendedSurface ? d->extendedSurface->windowFlags() : WaylandSurface::WindowFlags(0); + m_compositor->frameFinished(this); } -QPoint Surface::lastMousePos() const -{ - Q_D(const Surface); - return d->lastLocalMousePos; +void Surface::doUpdate(const QRect &rect) { + if (postBuffer()) { + m_surfaceBuffer->setPosted(); // disown buffer.... + if (m_textureBuffer) { + m_textureBuffer->destructBufferState(); + m_textureBuffer = 0; + } + if (!m_bufferQueue.isEmpty()) { + qDebug() << "++++++++++++++++++++++++++++++++++++++++ recursive damage :-)"; + newCurrentBuffer(); + doUpdate(rect); + } + } else { + m_compositor->markSurfaceAsDirty(this); + emit m_waylandSurface->damaged(rect); + } } -void Surface::setExtendedSurface(ExtendedSurface *extendedSurface) -{ - Q_D(Surface); - d->extendedSurface = extendedSurface; +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; + } } -ExtendedSurface *Surface::extendedSurface() const +SurfaceBuffer *Surface::createSurfaceBuffer(struct wl_buffer *buffer) { - Q_D(const Surface); - return d->extendedSurface; + SurfaceBuffer *newBuffer = 0; + for (int i = 0; i < Surface::buffer_pool_size; i++) { + if (!m_bufferPool[i].isRegisteredWithBuffer()) { + newBuffer = &m_bufferPool[i]; + newBuffer->initialize(buffer); + break; + } + } + + Q_ASSERT(newBuffer); + return newBuffer; } -void Surface::setSubSurface(SubSurface *subSurface) -{ - Q_D(Surface); - d->subSurface = subSurface; +void Surface::frameFinishedInternal() { + if (m_surfaceBuffer) + m_surfaceBuffer->setFinished(); + + if (!m_bufferQueue.isEmpty()) { + newCurrentBuffer(); + if (m_surfaceBuffer) + doUpdate(m_surfaceBuffer->damageRect()); + } } -SubSurface *Surface::subSurface() const -{ - Q_D(const Surface); - return d->subSurface; +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())) { + return true; + } else { + qDebug() << "could not post buffer"; + } + } +#endif + return false; } -void Surface::setShellSurface(ShellSurface *shellSurface) +void Surface::attach(struct wl_buffer *buffer) { - Q_D(Surface); - d->shellSurface = shellSurface; + 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; + } + } + 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; } -ShellSurface *Surface::shellSurface() const +void Surface::damage(const QRect &rect) { - Q_D(const Surface); - return d->shellSurface; + 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); + else + qWarning() << "Surface::damage() null buffer"; + } } -Compositor *Surface::compositor() const +const struct wl_surface_interface Surface::surface_interface = { + Surface::surface_destroy, + Surface::surface_attach, + Surface::surface_damage, + Surface::surface_frame +}; + +void Surface::surface_destroy(struct wl_client *, struct wl_resource *surface_resource) { - Q_D(const Surface); - return d->compositor; + wl_resource_destroy(surface_resource,Compositor::currentTimeMsecs()); } -void Surface::sendFrameCallback() +void Surface::surface_attach(struct wl_client *client, struct wl_resource *surface, + struct wl_resource *buffer, int x, int y) { - Q_D(Surface); - - d->frameFinished(); - - uint time = Compositor::currentTimeMsecs(); - struct wl_resource *frame_callback; - wl_list_for_each(frame_callback, &d->frame_callback_list, link) { - wl_resource_post_event(frame_callback,WL_CALLBACK_DONE,time); - wl_resource_destroy(frame_callback,Compositor::currentTimeMsecs()); - } - - wl_list_init(&d->frame_callback_list); + Q_UNUSED(client); + Q_UNUSED(x); + Q_UNUSED(y); + reinterpret_cast<Surface *>(surface)->attach(reinterpret_cast<struct wl_buffer *>(buffer)); } -void Surface::frameFinished() +void Surface::surface_damage(struct wl_client *client, struct wl_resource *surface, + int32_t x, int32_t y, int32_t width, int32_t height) { - Q_D(Surface); - d->compositor->frameFinished(this); + Q_UNUSED(client); + reinterpret_cast<Surface *>(surface)->damage(QRect(x, y, width, height)); } - -void Surface::sendOnScreenVisibilityChange(bool visible) +void Surface::surface_frame(struct wl_client *client, + struct wl_resource *resource, + uint32_t callback) { - Q_D(Surface); - if (d->extendedSurface) { - d->extendedSurface->sendOnScreenVisibllity(visible); - } + Surface *surface = reinterpret_cast<Surface *>(resource); + struct wl_resource *frame_callback = wl_client_add_object(client,&wl_callback_interface,0,callback,surface); + wl_list_insert(&surface->m_frame_callback_list,&frame_callback->link); } } // namespace Wayland |