From b7a1f2b3cf7e8965f17bccbb88f72829008b7ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Thu, 20 Jun 2013 08:30:31 +0200 Subject: [PATCH] Support resizing of Wayland ShmPool The Wayland::Buffer no longer holds the exact memory address but only the offset in the pool. The actual address of the pool is only known to the ShmPool which allows us to remap a resized file. If a new buffer cannot be provided by the given pool, it gets now resized to the new needed size. This allows us to only create a very small pool. --- wayland_backend.cpp | 38 ++++++++++++++++++++++++++++++-------- wayland_backend.h | 21 +++++++++++---------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/wayland_backend.cpp b/wayland_backend.cpp index dae7557a57..cff5829cee 100644 --- a/wayland_backend.cpp +++ b/wayland_backend.cpp @@ -404,12 +404,12 @@ void X11CursorTracker::resetCursor() } } -Buffer::Buffer(wl_buffer* buffer, const QSize& size, int32_t stride, void* address) +Buffer::Buffer(wl_buffer* buffer, const QSize& size, int32_t stride, size_t offset) : m_nativeBuffer(buffer) , m_released(false) , m_size(size) , m_stride(stride) - , m_address(address) + , m_offset(offset) { wl_buffer_add_listener(m_nativeBuffer, &s_bufferListener, this); } @@ -421,14 +421,14 @@ Buffer::~Buffer() void Buffer::copy(const void* src) { - memcpy(m_address, src, m_size.height()*m_stride); + memcpy((char*)WaylandBackend::self()->shmPool()->poolAddress() + m_offset, src, m_size.height()*m_stride); } ShmPool::ShmPool(wl_shm *shm) : m_shm(shm) , m_pool(NULL) , m_poolData(NULL) - , m_size(1024 * 1024) // TODO: useful size? + , m_size(1024) , m_tmpFile(new QTemporaryFile()) , m_valid(createPool()) , m_offset(0) @@ -447,6 +447,7 @@ ShmPool::~ShmPool() if (m_shm) { wl_shm_destroy(m_shm); } + m_tmpFile->close(); } bool ShmPool::createPool() @@ -466,7 +467,23 @@ bool ShmPool::createPool() qDebug() << "Creating Shm pool failed"; return false; } - m_tmpFile->close(); + return true; +} + +bool ShmPool::resizePool(int32_t newSize) +{ + if (ftruncate(m_tmpFile->handle(), newSize) < 0) { + qDebug() << "Could not set new size for Shm pool file"; + return false; + } + wl_shm_pool_resize(m_pool, newSize); + munmap(m_poolData, m_size); + m_poolData = mmap(NULL, newSize, PROT_READ | PROT_WRITE, MAP_SHARED, m_tmpFile->handle(), 0); + m_size = newSize; + if (!m_poolData) { + qDebug() << "Resizing Shm pool failed"; + return false; + } return true; } @@ -508,15 +525,20 @@ Buffer *ShmPool::getBuffer(const QSize &size, int32_t stride) buffer->setReleased(false); return buffer; } - // TODO: test whether buffer needs resizing + const int32_t byteCount = size.height() * stride; + if (m_offset + byteCount > m_size) { + if (!resizePool(m_size + byteCount)) { + return NULL; + } + } // we don't have a buffer which we could reuse - need to create a new one wl_buffer *native = wl_shm_pool_create_buffer(m_pool, m_offset, size.width(), size.height(), stride, WL_SHM_FORMAT_ARGB8888); if (!native) { return NULL; } - Buffer *buffer = new Buffer(native, size, stride, (char *)m_poolData + m_offset); - m_offset += size.height() * stride; + Buffer *buffer = new Buffer(native, size, stride, m_offset); + m_offset += byteCount; m_buffers.append(buffer); return buffer; } diff --git a/wayland_backend.h b/wayland_backend.h index 45ad5c48f7..703b6ef3c0 100644 --- a/wayland_backend.h +++ b/wayland_backend.h @@ -82,13 +82,12 @@ private: class Buffer { public: - Buffer(wl_buffer *buffer, const QSize &size, int32_t stride, void *address); + Buffer(wl_buffer *buffer, const QSize &size, int32_t stride, size_t offset); ~Buffer(); void copy(const void *src); void setReleased(bool released); wl_buffer *buffer() const; - void *address() const; const QSize &size() const; int32_t stride() const; bool isReleased() const; @@ -97,7 +96,7 @@ private: bool m_released; QSize m_size; int32_t m_stride; - void *m_address; + size_t m_offset; }; class ShmPool @@ -108,13 +107,15 @@ public: bool isValid() const; wl_buffer *createBuffer(const QImage &image); wl_buffer *createBuffer(const QSize &size, int32_t stride, const void *src); + void *poolAddress() const; private: bool createPool(); + bool resizePool(int32_t newSize); Buffer* getBuffer(const QSize &size, int32_t stride); wl_shm *m_shm; wl_shm_pool *m_pool; void *m_poolData; - size_t m_size; + int32_t m_size; QScopedPointer m_tmpFile; bool m_valid; int m_offset; @@ -217,6 +218,12 @@ bool ShmPool::isValid() const return m_valid; } +inline +void* ShmPool::poolAddress() const +{ + return m_poolData; +} + inline wl_display *WaylandBackend::display() { @@ -265,12 +272,6 @@ const QSize &WaylandBackend::shellSurfaceSize() const return m_shellSurfaceSize; } -inline -void* Buffer::address() const -{ - return m_address; -} - inline wl_buffer* Buffer::buffer() const {