diff options
author | Jørgen Lind <jorgen.lind@nokia.com> | 2011-12-21 09:03:49 +0100 |
---|---|---|
committer | Andy Nichols <andy.nichols@nokia.com> | 2011-12-22 15:55:49 +0100 |
commit | 35f4eeb5c9e5994124d1eb9dbebe2edd6912be8b (patch) | |
tree | 2fabef5ab63a7eccf00eec7bf7a2520456c31a7e /src/compositor/wayland_wrapper | |
parent | d203e39441bbc5fdc9d340540e157eb06e7761b0 (diff) |
Make it possible to hide surfaces
Change-Id: Ie3ba75335717e8dbae906c1a13cc8f852b77bd1b
Reviewed-by: Andy Nichols <andy.nichols@nokia.com>
Diffstat (limited to 'src/compositor/wayland_wrapper')
-rw-r--r-- | src/compositor/wayland_wrapper/wlsurface.cpp | 354 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/wlsurface.h | 8 |
2 files changed, 212 insertions, 150 deletions
diff --git a/src/compositor/wayland_wrapper/wlsurface.cpp b/src/compositor/wayland_wrapper/wlsurface.cpp index ee97bbb87..1730f141e 100644 --- a/src/compositor/wayland_wrapper/wlsurface.cpp +++ b/src/compositor/wayland_wrapper/wlsurface.cpp @@ -66,134 +66,153 @@ namespace Wayland { +static const int buffer_pool_size = 3; + struct surface_buffer_destroy_listener { struct wl_listener listener; - struct wl_buffer *buffer; - class SurfacePrivate *surfacePrivate; - struct wl_list link; + class SurfaceBuffer *surfaceBuffer; }; -const struct wl_surface_interface Surface::surface_interface = { - Surface::surface_destroy, - Surface::surface_attach, - Surface::surface_damage, - Surface::surface_frame -}; -class SurfacePrivate +class SurfaceBuffer { + static int counter; public: - SurfacePrivate(struct wl_client *client, Compositor *compositor) - : client(client) - , compositor(compositor) - , textureCreatedForBuffer(false) - , directRenderBuffer(0) - , processId(0) - , previousBuffer(0) - , surfaceBuffer(0) - , surfaceType(WaylandSurface::Invalid) - , extendedSurface(0) + SurfaceBuffer() + : m_buffer(0) + , m_texture(0) + , m_is_released_sent(false) + , m_is_registered_for_buffer(false) + { + } + ~SurfaceBuffer() + { + if (m_is_registered_for_buffer) + destructBufferState(); + } + void initialize(struct wl_buffer *buffer) { -#ifdef QT_COMPOSITOR_WAYLAND_GL - texture_id = 0; -#endif - wl_list_init(&frame_callback_list); - wl_list_init(&buffer_destroy_listener_list); + m_buffer = buffer; + m_texture = 0; + m_is_released_sent = false; + m_is_registered_for_buffer = true; + 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); } - static void destroy_listener_callback(struct wl_listener *listener, - struct wl_resource *resource, uint32_t time) + void destructBufferState() { - Q_UNUSED(resource); - Q_UNUSED(time); - struct surface_buffer_destroy_listener *destroy_listener = - reinterpret_cast<struct surface_buffer_destroy_listener *>(listener); - SurfacePrivate *d = destroy_listener->surfacePrivate; - if (d->surfaceBuffer == destroy_listener->buffer) { - d->surfaceBuffer = 0; - d->surfaceType = WaylandSurface::Invalid; -#ifdef QT_COMPOSITOR_WAYLAND_GL - if (d->textureCreatedForBuffer) { - glDeleteTextures(1,&d->texture_id); - d->textureCreatedForBuffer = false; - d->texture_id = 0; - } -#endif - } - if (d->directRenderBuffer == destroy_listener->buffer) { - d->directRenderBuffer = 0; - } - if (d->previousBuffer == destroy_listener->buffer) { - d->previousBuffer = 0; + destroyTexture(); + if (m_buffer) { + wl_list_remove(&m_destroy_listener.listener.link); + sendRelease(); } - d->removeFromBufferDestroyListenerList(destroy_listener->buffer); - delete destroy_listener; + m_buffer = 0; + m_is_registered_for_buffer = false; } - void addToBufferDestoryListenerList(struct wl_buffer *buffer) + + 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() { - struct surface_buffer_destroy_listener *destroy_listener; - wl_list_for_each(destroy_listener,&buffer_destroy_listener_list,link) { - if (destroy_listener->buffer == buffer) - return; - } - destroy_listener = new struct surface_buffer_destroy_listener; - destroy_listener->buffer = buffer; - destroy_listener->surfacePrivate = this; - destroy_listener->listener.func = destroy_listener_callback; - wl_list_insert(&buffer->resource.destroy_listener_list,&destroy_listener->listener.link); - wl_list_insert(&buffer_destroy_listener_list,&destroy_listener->link); + Q_ASSERT(m_buffer); + wl_resource_post_event(&m_buffer->resource, WL_BUFFER_RELEASE); + m_buffer = 0; + } + inline bool textureCreated() const + { + return m_texture; } - void removeFromBufferDestroyListenerList(struct wl_buffer *buffer) + inline GLuint texture() { - struct surface_buffer_destroy_listener *destroy_listener; - wl_list_for_each(destroy_listener, &buffer_destroy_listener_list, link) { - if (destroy_listener->buffer == buffer) - break; - } - if (destroy_listener) { - qDebug() << "removing listener"; - wl_list_remove(&destroy_listener->link); - } + if (m_buffer) + return m_texture; + return 0; } - WaylandSurface::Type type() const { - if (surfaceType == WaylandSurface::Invalid) { - SurfacePrivate *that = const_cast<SurfacePrivate *>(this); - if (qtSurface->handle() == compositor->directRenderSurface()) { - that->surfaceType = WaylandSurface::Direct; - } else if (surfaceBuffer && wl_buffer_is_shm(surfaceBuffer)) { - that->surfaceType = WaylandSurface::Shm; - } else if (surfaceBuffer){ - that->surfaceType = WaylandSurface::Texture; - } + 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; } - return surfaceType; +#endif } - void attach(struct wl_buffer *buffer) { - addToBufferDestoryListenerList(buffer); - bool emitMap = !surfaceBuffer; + inline struct wl_buffer *handle() const { return m_buffer; } +private: + struct wl_buffer *m_buffer; + struct surface_buffer_destroy_listener m_destroy_listener; + bool m_is_released_sent; + bool m_is_registered_for_buffer; - if (surfaceBuffer && ! textureCreatedForBuffer && surfaceBuffer != directRenderBuffer) { - qWarning() << "### WaylandSurface::attach() releasing undisplayed buffer ###"; - removeFromBufferDestroyListenerList(surfaceBuffer); - wl_resource_post_event(&surfaceBuffer->resource, WL_BUFFER_RELEASE); - } - surfaceBuffer = buffer; - surfaceType = WaylandSurface::Invalid; - textureCreatedForBuffer = false; - if (emitMap) { - qtSurface->mapped(QSize(surfaceBuffer->width,surfaceBuffer->height)); - } +#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; } +}; + +int SurfaceBuffer::counter = 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, struct wl_client *client, Compositor *compositor) + : q_ptr(surface) + , client(client) + , compositor(compositor) + , directRenderBuffer(0) + , processId(0) + , textureBuffer(0) + , surfaceBuffer(0) + , extendedSurface(0) - inline struct wl_buffer *buffer() const { return surfaceBuffer; } + + { + wl_list_init(&frame_callback_list); + } static void destroy_frame_callback(struct wl_resource *resource) { @@ -204,25 +223,23 @@ public: Compositor *compositor; WaylandSurface *qtSurface; -#ifdef QT_COMPOSITOR_WAYLAND_GL - GLuint texture_id; -#endif - bool textureCreatedForBuffer; - struct wl_buffer *directRenderBuffer; + SurfaceBuffer *surfaceBuffer; + SurfaceBuffer *textureBuffer; + SurfaceBuffer *directRenderBuffer; + qint64 processId; QByteArray authenticationToken; QVariantMap windowProperties; QPoint lastMousePos; - struct wl_buffer *previousBuffer; struct wl_list frame_callback_list; - struct wl_list buffer_destroy_listener_list; ExtendedSurface *extendedSurface; + + SurfaceBuffer bufferPool[buffer_pool_size]; private: - struct wl_buffer *surfaceBuffer; - WaylandSurface::Type surfaceType; + Surface *q_ptr; }; @@ -238,7 +255,7 @@ void Surface::surface_attach(struct wl_client *client, struct wl_resource *surfa Q_UNUSED(client); Q_UNUSED(x); Q_UNUSED(y); - reinterpret_cast<Surface *>(surface)->attach(buffer); + reinterpret_cast<Surface *>(surface)->attach(reinterpret_cast<struct wl_buffer *>(buffer)); } void Surface::surface_damage(struct wl_client *client, struct wl_resource *surface, @@ -258,7 +275,7 @@ void Surface::surface_frame(struct wl_client *client, } Surface::Surface(struct wl_client *client, Compositor *compositor) - : d_ptr(new SurfacePrivate(client,compositor)) + : d_ptr(new SurfacePrivate(this,client,compositor)) { base()->resource.client = client; d_ptr->qtSurface = new WaylandSurface(this); @@ -268,18 +285,23 @@ Surface::~Surface() { Q_D(Surface); d->compositor->surfaceDestroyed(this); -#ifdef QT_COMPOSITOR_WAYLAND_GL - if (d->compositor->graphicsHWIntegration()) - glDeleteTextures(1,&d->texture_id); -#endif delete d->qtSurface; } WaylandSurface::Type Surface::type() const { Q_D(const Surface); - return d->type(); + if (this == d->compositor->directRenderSurface()) { + return WaylandSurface::Direct; + } else if (d->surfaceBuffer && !d->surfaceBuffer->bufferIsDestroyed()) { + if (d->surfaceBuffer && d->surfaceBuffer->isShmBuffer()) { + return WaylandSurface::Shm; + } else if (d->surfaceBuffer){ + return WaylandSurface::Texture; + } + } + return WaylandSurface::Invalid; } bool Surface::isYInverted() const @@ -287,13 +309,11 @@ bool Surface::isYInverted() const #ifdef QT_COMPOSITOR_WAYLAND_GL Q_D(const Surface); - if (d->compositor->graphicsHWIntegration()) { - if (d->type() == WaylandSurface::Texture) { - //if (textureId()) { - return d->compositor->graphicsHWIntegration()->isYInverted(d->buffer()); - //} - } else if (d->type() == WaylandSurface::Direct) { - return d->compositor->graphicsHWIntegration()->isYInverted(d->buffer()); + if (d->compositor->graphicsHWIntegration() && !d->surfaceBuffer->bufferIsDestroyed()) { + if (type() == WaylandSurface::Texture) { + return d->compositor->graphicsHWIntegration()->isYInverted(d->surfaceBuffer->handle()); + } else if (type() == WaylandSurface::Direct) { + return d->compositor->graphicsHWIntegration()->isYInverted(d->surfaceBuffer->handle()); } } #endif @@ -301,25 +321,33 @@ bool Surface::isYInverted() const return false; } +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->surfaceBuffer || !d->surfaceBuffer->handle()) + return; #ifdef QT_COMPOSITOR_WAYLAND_GL - if (d->compositor->graphicsHWIntegration() && d->type() == WaylandSurface::Direct) { + if (d->compositor->graphicsHWIntegration() && type() == WaylandSurface::Direct) { //should the texture be deleted here, or should we explicitly delete it //when going into direct mode... - if (d->textureCreatedForBuffer) { - glDeleteTextures(1,&d->texture_id); - d->textureCreatedForBuffer = false; + if (d->surfaceBuffer->textureCreated()) { + d->surfaceBuffer->destroyTexture(); } - if (d->previousBuffer) { //previousBuffer means previous buffer turned into texture - wl_resource_post_event(&d->previousBuffer->resource,WL_BUFFER_RELEASE); - d->removeFromBufferDestroyListenerList(d->previousBuffer); - d->previousBuffer = 0; + if (d->textureBuffer) { //previousBuffer means previous buffer turned into texture + d->textureBuffer->destructBufferState(); + d->textureBuffer = 0; } - if (d->compositor->graphicsHWIntegration()->postBuffer(d->buffer())) { - d->directRenderBuffer = d->buffer(); + if (d->compositor->graphicsHWIntegration()->postBuffer(d->surfaceBuffer->handle())) { + d->directRenderBuffer->destructBufferState(); + d->directRenderBuffer = d->surfaceBuffer; + d->surfaceBuffer = 0; emit d->qtSurface->damaged(rect); return; } @@ -334,8 +362,8 @@ void Surface::damage(const QRect &rect) QImage Surface::image() const { Q_D(const Surface); - if (d->type() == WaylandSurface::Shm && d->buffer()) { - ShmBuffer *shmBuffer = static_cast<ShmBuffer *>(d->buffer()->user_data); + if (type() == WaylandSurface::Shm && d->surfaceBuffer && d->surfaceBuffer->handle()) { + ShmBuffer *shmBuffer = static_cast<ShmBuffer *>(d->surfaceBuffer->handle()->user_data); return shmBuffer->image(); } return QImage(); @@ -345,28 +373,60 @@ QImage Surface::image() const GLuint Surface::textureId(QOpenGLContext *context) const { Q_D(const Surface); - if (d->compositor->graphicsHWIntegration() && d->type() == WaylandSurface::Texture - && !d->textureCreatedForBuffer) { - if (d->texture_id) - glDeleteTextures(1,&d->texture_id); - if (d->previousBuffer) { - wl_resource_post_event(&d->previousBuffer->resource,WL_BUFFER_RELEASE); - const_cast<Surface *>(this)->d_func()->removeFromBufferDestroyListenerList(d->previousBuffer); - } + + if (d->compositor->graphicsHWIntegration() && type() == WaylandSurface::Texture + && !d->surfaceBuffer->textureCreated()) { Surface *that = const_cast<Surface *>(this); + + if (d->textureBuffer) { + d->textureBuffer->destructBufferState(); + that->d_func()->textureBuffer = 0; + } + if (d->directRenderBuffer) { + d->directRenderBuffer->destructBufferState(); + that->d_func()->directRenderBuffer = 0; + } GraphicsHardwareIntegration *hwIntegration = d->compositor->graphicsHWIntegration(); - that->d_func()->previousBuffer = d->buffer(); - that->d_func()->texture_id = hwIntegration->createTextureFromBuffer(d->buffer(), context); - that->d_func()->textureCreatedForBuffer = true; + that->d_func()->textureBuffer = d->surfaceBuffer; + that->d_func()->textureBuffer->setTexture(hwIntegration->createTextureFromBuffer(d->textureBuffer->handle(), context)); } - return d->texture_id; + return d->textureBuffer->texture(); } #endif // QT_COMPOSITOR_WAYLAND_GL -void Surface::attach(struct wl_resource *buffer) +void Surface::attach(struct wl_buffer *buffer) { Q_D(Surface); - d->attach(reinterpret_cast<struct wl_buffer *>(buffer)); + SurfaceBuffer *newBuffer = 0; + if (buffer) { + for (int i = 0; i < buffer_pool_size; i++) { + if (!d->bufferPool[i].isRegisteredWithBuffer()) { + newBuffer = &d->bufferPool[i]; + newBuffer->initialize(buffer); + break; + } + } + } + Q_ASSERT(newBuffer); + + bool emitMap = !d->surfaceBuffer && buffer; + bool emitUnmap = d->surfaceBuffer && !buffer; + + if (d->surfaceBuffer && d->surfaceBuffer != d->directRenderBuffer) { + qDebug() << "### WaylandSurface::attach() releasing undisplayed buffer ###"; + if (d->textureBuffer == d->surfaceBuffer) + d->textureBuffer = 0; + d->surfaceBuffer->destructBufferState(); + d->surfaceBuffer = 0; + } + if (d->surfaceBuffer) + qDebug() << "Still a surfacebuffer!"; + d->surfaceBuffer = newBuffer; + if (emitMap) { + d->qtSurface->mapped(QSize(d->surfaceBuffer->width(),d->surfaceBuffer->height())); + } else if (emitUnmap) { + d->qtSurface->unmapped(); + } } WaylandSurface * Surface::handle() const diff --git a/src/compositor/wayland_wrapper/wlsurface.h b/src/compositor/wayland_wrapper/wlsurface.h index b994ae94a..425e3ce88 100644 --- a/src/compositor/wayland_wrapper/wlsurface.h +++ b/src/compositor/wayland_wrapper/wlsurface.h @@ -77,10 +77,9 @@ public: WaylandSurface::Type type() const; bool isYInverted() const; - uint id() const { return base()->resource.object.id; } - void attach(struct wl_resource *buffer); + bool visible() const; - void damage(const QRect &rect); + uint id() const { return base()->resource.object.id; } QImage image() const; @@ -127,6 +126,9 @@ protected: QScopedPointer<SurfacePrivate> d_ptr; private: Q_DISABLE_COPY(Surface) + void attach(struct wl_buffer *buffer); + void damage(const QRect &rect); + static void surface_destroy(struct wl_client *client, struct wl_resource *_surface); static void surface_attach(struct wl_client *client, struct wl_resource *surface, struct wl_resource *buffer, int x, int y); |