diff options
Diffstat (limited to 'src/compositor/wayland_wrapper/wlsurface.cpp')
-rw-r--r-- | src/compositor/wayland_wrapper/wlsurface.cpp | 250 |
1 files changed, 126 insertions, 124 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<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 = { |