Client: Prune stale buffers in QWaylandShmBackingStore
A backing store may sometimes allocate an extra buffer and keep it even though the buffer is never touched again. This change makes the QWaylandShmBackingStore clean up the old buffers more aggressively. Specifically, * if a buffer is referenced by the compositor and has a different size, there is no need to wait for the buffer to be released, it can be destroyed immediately * if a buffer has not been used for the past 50 frames, it probably won't be used any time soon so it can be disposed Depending on the compositor implementation details, the QWaylandShmBackingStore is likely to hold either one or two buffers now. Note that the backing store can still sometimes have more buffers because Qt widgets not always use QWindow::requestUpdate(). Change-Id: I57428d457d889dd07c4beb641cf380b1aceb88c2 Reviewed-by: David Edmundson <davidedmundson@kde.org>
This commit is contained in:
parent
412b1ecd5c
commit
a99d09f0b3
@ -255,23 +255,33 @@ void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &)
|
||||
|
||||
QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size, bool &bufferWasRecreated)
|
||||
{
|
||||
static const int MAX_BUFFERS = 5;
|
||||
static const int MAX_AGE = 10 * MAX_BUFFERS;
|
||||
bufferWasRecreated = false;
|
||||
|
||||
const auto copy = mBuffers; // remove when ported to vector<unique_ptr> + remove_if
|
||||
for (QWaylandShmBuffer *b : copy) {
|
||||
if (!b->busy()) {
|
||||
if (b->size() == size) {
|
||||
return b;
|
||||
} else {
|
||||
mBuffers.remove(b);
|
||||
if (mBackBuffer == b)
|
||||
mBackBuffer = nullptr;
|
||||
delete b;
|
||||
}
|
||||
// Prune buffers that have not been used in a while or with different size.
|
||||
for (auto i = mBuffers.size() - 1; i >= 0; --i) {
|
||||
QWaylandShmBuffer *buffer = mBuffers[i];
|
||||
if (buffer->age() > MAX_AGE || buffer->size() != size) {
|
||||
mBuffers.removeAt(i);
|
||||
if (mBackBuffer == buffer)
|
||||
mBackBuffer = nullptr;
|
||||
delete buffer;
|
||||
}
|
||||
}
|
||||
|
||||
static const size_t MAX_BUFFERS = 5;
|
||||
QWaylandShmBuffer *buffer = nullptr;
|
||||
for (QWaylandShmBuffer *candidate : std::as_const(mBuffers)) {
|
||||
if (candidate->busy())
|
||||
continue;
|
||||
|
||||
if (!buffer || candidate->age() < buffer->age())
|
||||
buffer = candidate;
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
return buffer;
|
||||
|
||||
if (mBuffers.size() < MAX_BUFFERS) {
|
||||
QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format();
|
||||
QWaylandShmBuffer *b = new QWaylandShmBuffer(mDisplay, size, format, waylandWindow()->scale());
|
||||
@ -327,11 +337,12 @@ bool QWaylandShmBackingStore::recreateBackBufferIfNeeded()
|
||||
|
||||
mBackBuffer = buffer;
|
||||
|
||||
// ensure the new buffer is at the beginning of the list so next time getBuffer() will pick
|
||||
// it if possible
|
||||
if (mBuffers.front() != buffer) {
|
||||
mBuffers.remove(buffer);
|
||||
mBuffers.push_front(buffer);
|
||||
for (QWaylandShmBuffer *buffer : std::as_const(mBuffers)) {
|
||||
if (mBackBuffer == buffer) {
|
||||
buffer->setAge(0);
|
||||
} else {
|
||||
buffer->setAge(buffer->age() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (windowDecoration() && window()->isVisible() && oldSizeInBytes != newSizeInBytes)
|
||||
|
@ -22,8 +22,6 @@
|
||||
#include <qpa/qplatformwindow.h>
|
||||
#include <QMutex>
|
||||
|
||||
#include <list>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QtWaylandClient {
|
||||
@ -44,12 +42,17 @@ public:
|
||||
QImage *imageInsideMargins(const QMargins &margins);
|
||||
|
||||
QRegion &dirtyRegion() { return mDirtyRegion; }
|
||||
|
||||
uint age() const { return mAge; }
|
||||
void setAge(uint age) { mAge = age; }
|
||||
|
||||
private:
|
||||
QImage mImage;
|
||||
struct wl_shm_pool *mShmPool = nullptr;
|
||||
QMargins mMargins;
|
||||
QImage *mMarginsImage = nullptr;
|
||||
QRegion mDirtyRegion;
|
||||
uint mAge = 0;
|
||||
};
|
||||
|
||||
class Q_WAYLANDCLIENT_EXPORT QWaylandShmBackingStore : public QPlatformBackingStore
|
||||
@ -84,7 +87,7 @@ private:
|
||||
QWaylandShmBuffer *getBuffer(const QSize &size, bool &bufferWasRecreated);
|
||||
|
||||
QWaylandDisplay *mDisplay = nullptr;
|
||||
std::list<QWaylandShmBuffer *> mBuffers;
|
||||
QList<QWaylandShmBuffer *> mBuffers;
|
||||
QWaylandShmBuffer *mFrontBuffer = nullptr;
|
||||
QWaylandShmBuffer *mBackBuffer = nullptr;
|
||||
bool mPainting = false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user