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.
This commit is contained in:
parent
53c09ce7bd
commit
b7a1f2b3cf
2 changed files with 41 additions and 18 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue