Centralize WindowPixmap buffer updating code

Uses a setter and clear method pattern rather than having the code
repeated.
Instead of keeping a QPointer, now we are a QObject and we get notified
about destruction intention directly, so we can clear the pointer when
necessary.
master
Aleix Pol 2020-09-19 00:40:57 +02:00 committed by Aleix Pol Gonzalez
parent 26950a65a6
commit 61e655f7f7
5 changed files with 41 additions and 39 deletions

View File

@ -345,8 +345,8 @@ bool AbstractEglTexture::loadTexture(WindowPixmap *pixmap)
{ {
// FIXME: Refactor this method. // FIXME: Refactor this method.
const auto &buffer = pixmap->buffer(); const auto buffer = pixmap->buffer();
if (buffer.isNull()) { if (!buffer) {
if (updateFromFBO(pixmap->fbo())) { if (updateFromFBO(pixmap->fbo())) {
return true; return true;
} }
@ -371,8 +371,8 @@ void AbstractEglTexture::updateTexture(WindowPixmap *pixmap)
{ {
// FIXME: Refactor this method. // FIXME: Refactor this method.
const auto &buffer = pixmap->buffer(); const auto buffer = pixmap->buffer();
if (buffer.isNull()) { if (!buffer) {
if (updateFromFBO(pixmap->fbo())) { if (updateFromFBO(pixmap->fbo())) {
return; return;
} }

View File

@ -627,7 +627,7 @@ bool EglStreamTexture::loadTexture(WindowPixmap *pixmap)
using namespace KWaylandServer; using namespace KWaylandServer;
SurfaceInterface *surface = pixmap->surface(); SurfaceInterface *surface = pixmap->surface();
const EglStreamBackend::StreamTexture *st = m_backend->lookupStreamTexture(surface); const EglStreamBackend::StreamTexture *st = m_backend->lookupStreamTexture(surface);
if (!pixmap->buffer().isNull() && st != nullptr) { if (pixmap->buffer() && st != nullptr) {
glGenTextures(1, &m_texture); glGenTextures(1, &m_texture);
texture()->setWrapMode(GL_CLAMP_TO_EDGE); texture()->setWrapMode(GL_CLAMP_TO_EDGE);
@ -655,7 +655,7 @@ void EglStreamTexture::updateTexture(WindowPixmap *pixmap)
using namespace KWaylandServer; using namespace KWaylandServer;
SurfaceInterface *surface = pixmap->surface(); SurfaceInterface *surface = pixmap->surface();
const EglStreamBackend::StreamTexture *st = m_backend->lookupStreamTexture(surface); const EglStreamBackend::StreamTexture *st = m_backend->lookupStreamTexture(surface);
if (!pixmap->buffer().isNull() && st != nullptr) { if (pixmap->buffer() && st != nullptr) {
if (attachBuffer(surface->buffer())) { if (attachBuffer(surface->buffer())) {
createFbo(); createFbo();

View File

@ -417,7 +417,7 @@ void QPainterWindowPixmap::update()
m_image = internalImage(); m_image = internalImage();
return; return;
} }
if (b.isNull()) { if (!b) {
m_image = QImage(); m_image = QImage();
return; return;
} }

View File

@ -1118,11 +1118,7 @@ WindowPixmap::~WindowPixmap()
if (m_pixmap != XCB_WINDOW_NONE) { if (m_pixmap != XCB_WINDOW_NONE) {
xcb_free_pixmap(connection(), m_pixmap); xcb_free_pixmap(connection(), m_pixmap);
} }
if (m_buffer) { clear();
using namespace KWaylandServer;
QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref);
m_buffer->unref();
}
} }
void WindowPixmap::create() void WindowPixmap::create()
@ -1170,13 +1166,33 @@ void WindowPixmap::create()
m_window->discardQuads(); m_window->discardQuads();
} }
void WindowPixmap::clear()
{
setBuffer(nullptr);
}
void WindowPixmap::setBuffer(KWaylandServer::BufferInterface *buffer)
{
if (buffer == m_buffer) {
return;
}
if (m_buffer) {
disconnect(m_buffer, &KWaylandServer::BufferInterface::aboutToBeDestroyed, this, &WindowPixmap::clear);
m_buffer->unref();
}
m_buffer = buffer;
if (m_buffer) {
m_buffer->ref();
connect(m_buffer, &KWaylandServer::BufferInterface::aboutToBeDestroyed, this, &WindowPixmap::clear);
}
}
void WindowPixmap::update() void WindowPixmap::update()
{ {
using namespace KWaylandServer; using namespace KWaylandServer;
if (SurfaceInterface *s = surface()) { if (SurfaceInterface *s = surface()) {
QVector<WindowPixmap*> oldTree = m_children; QVector<WindowPixmap*> oldTree = m_children;
QVector<WindowPixmap*> children; QVector<WindowPixmap*> children;
using namespace KWaylandServer;
const auto subSurfaces = s->childSubSurfaces(); const auto subSurfaces = s->childSubSurfaces();
for (const auto &subSurface : subSurfaces) { for (const auto &subSurface : subSurfaces) {
if (subSurface.isNull()) { if (subSurface.isNull()) {
@ -1198,34 +1214,16 @@ void WindowPixmap::update()
setChildren(children); setChildren(children);
qDeleteAll(oldTree); qDeleteAll(oldTree);
if (auto b = s->buffer()) { if (auto b = s->buffer()) {
if (b == m_buffer) { setBuffer(b);
// no change
return;
}
if (m_buffer) {
QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref);
m_buffer->unref();
}
m_buffer = b;
m_buffer->ref();
QObject::connect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref);
} else if (m_subSurface) { } else if (m_subSurface) {
if (m_buffer) { clear();
QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref);
m_buffer->unref();
m_buffer.clear();
}
} }
} else if (toplevel()->internalFramebufferObject()) { } else if (toplevel()->internalFramebufferObject()) {
m_fbo = toplevel()->internalFramebufferObject(); m_fbo = toplevel()->internalFramebufferObject();
} else if (!toplevel()->internalImageObject().isNull()) { } else if (!toplevel()->internalImageObject().isNull()) {
m_internalImage = toplevel()->internalImageObject(); m_internalImage = toplevel()->internalImageObject();
} else { } else {
if (m_buffer) { clear();
QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref);
m_buffer->unref();
m_buffer.clear();
}
} }
} }
@ -1237,7 +1235,7 @@ WindowPixmap *WindowPixmap::createChild(const QPointer<KWaylandServer::SubSurfac
bool WindowPixmap::isValid() const bool WindowPixmap::isValid() const
{ {
if (!m_buffer.isNull() || !m_fbo.isNull() || !m_internalImage.isNull()) { if (m_buffer || !m_fbo.isNull() || !m_internalImage.isNull()) {
return true; return true;
} }
return m_pixmap != XCB_PIXMAP_NONE; return m_pixmap != XCB_PIXMAP_NONE;

12
scene.h
View File

@ -415,8 +415,9 @@ private:
* This class is intended to be inherited for the needs of the compositor backends which need further mapping from * This class is intended to be inherited for the needs of the compositor backends which need further mapping from
* the native pixmap to the respective rendering format. * the native pixmap to the respective rendering format.
*/ */
class KWIN_EXPORT WindowPixmap class KWIN_EXPORT WindowPixmap : public QObject
{ {
Q_OBJECT
public: public:
virtual ~WindowPixmap(); virtual ~WindowPixmap();
/** /**
@ -448,7 +449,7 @@ public:
/** /**
* @return The Wayland BufferInterface for this WindowPixmap. * @return The Wayland BufferInterface for this WindowPixmap.
*/ */
QPointer<KWaylandServer::BufferInterface> buffer() const; KWaylandServer::BufferInterface *buffer() const;
const QSharedPointer<QOpenGLFramebufferObject> &fbo() const; const QSharedPointer<QOpenGLFramebufferObject> &fbo() const;
QImage internalImage() const; QImage internalImage() const;
/** /**
@ -575,12 +576,15 @@ protected:
} }
private: private:
void setBuffer(KWaylandServer::BufferInterface *buffer);
void clear();
Scene::Window *m_window; Scene::Window *m_window;
xcb_pixmap_t m_pixmap; xcb_pixmap_t m_pixmap;
QSize m_pixmapSize; QSize m_pixmapSize;
bool m_discarded; bool m_discarded;
QRect m_contentsRect; QRect m_contentsRect;
QPointer<KWaylandServer::BufferInterface> m_buffer; KWaylandServer::BufferInterface *m_buffer = nullptr;
QSharedPointer<QOpenGLFramebufferObject> m_fbo; QSharedPointer<QOpenGLFramebufferObject> m_fbo;
QImage m_internalImage; QImage m_internalImage;
WindowPixmap *m_parent = nullptr; WindowPixmap *m_parent = nullptr;
@ -678,7 +682,7 @@ Shadow* Scene::Window::shadow()
} }
inline inline
QPointer<KWaylandServer::BufferInterface> WindowPixmap::buffer() const KWaylandServer::BufferInterface *WindowPixmap::buffer() const
{ {
return m_buffer; return m_buffer;
} }