core: Introduce base GraphicsBuffer
Currently, there exists the separation between the buffers provided by the clients and the buffers created by the compositor. In hindsight, this separation is not great because it leads to specialized code paths in the output backend. For example, we have a separate code path for direct scanout and presenting composited frame. But you could view the latter case as "direct scanout of a compositor buffer". The main idea behind the buffer type is to provide a base buffer type for client buffers and composited frame buffers (not drm fbs) that we could pass around, import as textures, etc.
This commit is contained in:
parent
c77b5909de
commit
3ac4f8a7dc
8 changed files with 126 additions and 75 deletions
|
@ -42,6 +42,7 @@ target_sources(kwin PRIVATE
|
|||
core/colorlut.cpp
|
||||
core/colorpipelinestage.cpp
|
||||
core/colortransformation.cpp
|
||||
core/graphicsbuffer.cpp
|
||||
core/inputbackend.cpp
|
||||
core/inputdevice.cpp
|
||||
core/output.cpp
|
||||
|
|
55
src/core/graphicsbuffer.cpp
Normal file
55
src/core/graphicsbuffer.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "core/graphicsbuffer.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
GraphicsBuffer::GraphicsBuffer(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool GraphicsBuffer::isReferenced() const
|
||||
{
|
||||
return m_refCount > 0;
|
||||
}
|
||||
|
||||
bool GraphicsBuffer::isDropped() const
|
||||
{
|
||||
return m_dropped;
|
||||
}
|
||||
|
||||
void GraphicsBuffer::ref()
|
||||
{
|
||||
++m_refCount;
|
||||
}
|
||||
|
||||
void GraphicsBuffer::unref()
|
||||
{
|
||||
Q_ASSERT(m_refCount > 0);
|
||||
--m_refCount;
|
||||
if (!m_refCount) {
|
||||
if (m_dropped) {
|
||||
delete this;
|
||||
} else {
|
||||
Q_EMIT released();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsBuffer::drop()
|
||||
{
|
||||
m_dropped = true;
|
||||
Q_EMIT dropped();
|
||||
|
||||
if (!m_refCount) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KWin
|
59
src/core/graphicsbuffer.h
Normal file
59
src/core/graphicsbuffer.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2023 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kwin_export.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
/**
|
||||
* The GraphicsBuffer class represents a chunk of memory containing graphics data.
|
||||
*
|
||||
* A graphics buffer can be referenced. In which case, it won't be destroyed until all
|
||||
* references are dropped. You can use the isDropped() function to check whether the
|
||||
* buffer has been marked as destroyed.
|
||||
*/
|
||||
class KWIN_EXPORT GraphicsBuffer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GraphicsBuffer(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* This enum type is used to specify the corner where the origin is. That is, the
|
||||
* buffer corner where 0,0 is located.
|
||||
*/
|
||||
enum class Origin {
|
||||
TopLeft,
|
||||
BottomLeft,
|
||||
};
|
||||
|
||||
bool isReferenced() const;
|
||||
bool isDropped() const;
|
||||
|
||||
void ref();
|
||||
void unref();
|
||||
void drop();
|
||||
|
||||
virtual QSize size() const = 0;
|
||||
virtual bool hasAlphaChannel() const = 0;
|
||||
virtual Origin origin() const = 0;
|
||||
|
||||
Q_SIGNALS:
|
||||
void released();
|
||||
void dropped();
|
||||
|
||||
protected:
|
||||
int m_refCount = 0;
|
||||
bool m_dropped = false;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
|
@ -873,7 +873,7 @@ void TestWaylandSurface::testDestroyAttachedBuffer()
|
|||
// Let's try to destroy it
|
||||
delete m_shm;
|
||||
m_shm = nullptr;
|
||||
QTRY_VERIFY(serverSurface->buffer()->isDestroyed());
|
||||
QTRY_VERIFY(serverSurface->buffer()->isDropped());
|
||||
}
|
||||
|
||||
void TestWaylandSurface::testDestroyWithPendingCallback()
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "clientbuffer.h"
|
||||
#include "clientbuffer_p.h"
|
||||
|
||||
#include "qwayland-server-wayland.h"
|
||||
#include <wayland-server-protocol.h>
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
@ -30,6 +30,12 @@ void ClientBuffer::initialize(wl_resource *resource)
|
|||
{
|
||||
Q_D(ClientBuffer);
|
||||
d->resource = resource;
|
||||
connect(this, &GraphicsBuffer::dropped, [d]() {
|
||||
d->resource = nullptr;
|
||||
});
|
||||
connect(this, &GraphicsBuffer::released, [d]() {
|
||||
wl_buffer_send_release(d->resource);
|
||||
});
|
||||
}
|
||||
|
||||
wl_resource *ClientBuffer::resource() const
|
||||
|
@ -38,47 +44,4 @@ wl_resource *ClientBuffer::resource() const
|
|||
return d->resource;
|
||||
}
|
||||
|
||||
bool ClientBuffer::isReferenced() const
|
||||
{
|
||||
Q_D(const ClientBuffer);
|
||||
return d->refCount > 0;
|
||||
}
|
||||
|
||||
bool ClientBuffer::isDestroyed() const
|
||||
{
|
||||
Q_D(const ClientBuffer);
|
||||
return d->isDestroyed;
|
||||
}
|
||||
|
||||
void ClientBuffer::ref()
|
||||
{
|
||||
Q_D(ClientBuffer);
|
||||
d->refCount++;
|
||||
}
|
||||
|
||||
void ClientBuffer::unref()
|
||||
{
|
||||
Q_D(ClientBuffer);
|
||||
Q_ASSERT(d->refCount > 0);
|
||||
--d->refCount;
|
||||
if (!isReferenced()) {
|
||||
if (isDestroyed()) {
|
||||
delete this;
|
||||
} else {
|
||||
wl_buffer_send_release(d->resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientBuffer::markAsDestroyed()
|
||||
{
|
||||
Q_D(ClientBuffer);
|
||||
if (!isReferenced()) {
|
||||
delete this;
|
||||
} else {
|
||||
d->resource = nullptr;
|
||||
d->isDestroyed = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KWaylandServer
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "kwin_export.h"
|
||||
#include "core/graphicsbuffer.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QObject>
|
||||
|
@ -27,7 +27,7 @@ class ClientBufferPrivate;
|
|||
* You can use the isDestroyed() function to check whether the wl_buffer object has been
|
||||
* destroyed.
|
||||
*/
|
||||
class KWIN_EXPORT ClientBuffer : public QObject
|
||||
class KWIN_EXPORT ClientBuffer : public KWin::GraphicsBuffer
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(ClientBuffer)
|
||||
|
@ -35,37 +35,12 @@ class KWIN_EXPORT ClientBuffer : public QObject
|
|||
public:
|
||||
~ClientBuffer() override;
|
||||
|
||||
/**
|
||||
* This enum type is used to specify the corner where the origin is. That's it, the
|
||||
* buffer corner where 0,0 is located.
|
||||
*/
|
||||
enum class Origin {
|
||||
TopLeft,
|
||||
BottomLeft,
|
||||
};
|
||||
|
||||
bool isReferenced() const;
|
||||
bool isDestroyed() const;
|
||||
|
||||
void ref();
|
||||
void unref();
|
||||
|
||||
/**
|
||||
* Returns the wl_resource for this ClientBuffer. If the buffer is destroyed, @c null
|
||||
* will be returned.
|
||||
*/
|
||||
wl_resource *resource() const;
|
||||
|
||||
/**
|
||||
* Returns the size in the native pixels. The returned size is unaffected by buffer
|
||||
* scale or other surface transforms, e.g. @c wp_viewport.
|
||||
*/
|
||||
virtual QSize size() const = 0;
|
||||
virtual bool hasAlphaChannel() const = 0;
|
||||
virtual Origin origin() const = 0;
|
||||
|
||||
void markAsDestroyed(); ///< @internal
|
||||
|
||||
protected:
|
||||
ClientBuffer(ClientBufferPrivate &dd);
|
||||
ClientBuffer(wl_resource *resource, ClientBufferPrivate &dd);
|
||||
|
|
|
@ -17,9 +17,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
int refCount = 0;
|
||||
wl_resource *resource = nullptr;
|
||||
bool isDestroyed = false;
|
||||
};
|
||||
|
||||
} // namespace KWaylandServer
|
||||
|
|
|
@ -232,7 +232,7 @@ void bufferDestroyCallback(wl_listener *listener, void *data)
|
|||
ClientBuffer *buffer = displayPrivate->q->clientBufferForResource(static_cast<wl_resource *>(data));
|
||||
displayPrivate->unregisterClientBuffer(buffer);
|
||||
|
||||
buffer->markAsDestroyed();
|
||||
buffer->drop();
|
||||
}
|
||||
|
||||
ClientBufferDestroyListener::ClientBufferDestroyListener(Display *display, ClientBuffer *buffer)
|
||||
|
|
Loading…
Reference in a new issue