backends/wayland: support direct scanout

This allows for (mostly) overhead-less pass-through of fullscreen content
to the host compositor
This commit is contained in:
Xaver Hugl 2024-02-13 16:29:48 +01:00
parent 2f4db693e3
commit c6be2b51a9
2 changed files with 26 additions and 3 deletions

View file

@ -14,6 +14,8 @@
#include "opengl/glrendertimequery.h"
#include "opengl/glutils.h"
#include "platformsupport/scenes/opengl/basiceglsurfacetexture_wayland.h"
#include "scene/surfaceitem_wayland.h"
#include "wayland/surface.h"
#include "wayland_backend.h"
#include "wayland_display.h"
#include "wayland_logging.h"
@ -109,17 +111,34 @@ bool WaylandEglPrimaryLayer::endFrame(const QRegion &renderedRegion, const QRegi
return true;
}
bool WaylandEglPrimaryLayer::scanout(SurfaceItem *surfaceItem)
{
Q_ASSERT(!m_presentationBuffer);
if (surfaceItem->size() != m_waylandOutput->modeSize()) {
return false;
}
SurfaceItemWayland *item = qobject_cast<SurfaceItemWayland *>(surfaceItem);
if (!item || !item->surface() || item->surface()->bufferTransform() != OutputTransform::Kind::Normal) {
return false;
}
m_presentationBuffer = m_backend->backend()->importBuffer(item->surface()->buffer());
return m_presentationBuffer;
}
void WaylandEglPrimaryLayer::present()
{
wl_buffer *buffer = m_backend->backend()->importBuffer(m_buffer->buffer());
Q_ASSERT(buffer);
if (!m_presentationBuffer) {
m_presentationBuffer = m_backend->backend()->importBuffer(m_buffer->buffer());
Q_ASSERT(m_presentationBuffer);
}
KWayland::Client::Surface *surface = m_waylandOutput->surface();
surface->attachBuffer(buffer);
surface->attachBuffer(m_presentationBuffer);
surface->damage(m_damageJournal.lastDamage());
surface->setScale(std::ceil(m_waylandOutput->scale()));
surface->commit();
Q_EMIT m_waylandOutput->outputChange(m_damageJournal.lastDamage());
m_presentationBuffer = nullptr;
m_swapchain->release(m_buffer);
}

View file

@ -15,6 +15,8 @@
#include <memory>
struct wl_buffer;
namespace KWin
{
class EglSwapchainSlot;
@ -42,6 +44,7 @@ public:
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
std::chrono::nanoseconds queryRenderTime() const override;
bool scanout(SurfaceItem *surfaceItem) override;
private:
WaylandOutput *m_waylandOutput;
@ -50,6 +53,7 @@ private:
std::shared_ptr<EglSwapchainSlot> m_buffer;
std::unique_ptr<GLRenderTimeQuery> m_query;
WaylandEglBackend *const m_backend;
wl_buffer *m_presentationBuffer = nullptr;
friend class WaylandEglBackend;
};