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.
icc-effect-5.14.5
Martin Gräßlin 2013-06-20 08:30:31 +02:00
parent 53c09ce7bd
commit b7a1f2b3cf
2 changed files with 41 additions and 18 deletions

View File

@ -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;
}

View File

@ -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<QTemporaryFile> 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
{