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)
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;
}
}
{
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;
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
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;
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());
+ }
+ }
}
}
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";
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 = {
#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)
{
}
{
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();
}
}
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()
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
}
}
#include <wayland-server.h>
+class GraphicsHardwareIntegration;
+class QOpenGLContext;
+
namespace Wayland {
struct surface_buffer_destroy_listener
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; }
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
};
-GLuint SurfaceBuffer::texture()
+GLuint SurfaceBuffer::texture() const
{
if (m_buffer)
return m_texture;