platforms/wayland: Add initial HiDPI support

This can be useful for test purposes and for people who have HiDPI monitors.
This commit is contained in:
Vlad Zahorodnii 2020-12-03 10:23:51 +02:00
parent 6b94be8652
commit 41a5362136
5 changed files with 35 additions and 37 deletions

View file

@ -50,8 +50,8 @@ EglWaylandOutput::EglWaylandOutput(WaylandOutput *output, QObject *parent)
bool EglWaylandOutput::init(EglWaylandBackend *backend)
{
auto surface = m_waylandOutput->surface();
const QSize &size = m_waylandOutput->geometry().size();
auto overlay = wl_egl_window_create(*surface, size.width(), size.height());
const QSize nativeSize = m_waylandOutput->geometry().size() * m_waylandOutput->scale();
auto overlay = wl_egl_window_create(*surface, nativeSize.width(), nativeSize.height());
if (!overlay) {
qCCritical(KWIN_WAYLAND_BACKEND) << "Creating Wayland Egl window failed";
return false;
@ -71,19 +71,15 @@ bool EglWaylandOutput::init(EglWaylandBackend *backend)
m_eglSurface = eglSurface;
connect(m_waylandOutput, &WaylandOutput::sizeChanged, this, &EglWaylandOutput::updateSize);
connect(m_waylandOutput, &WaylandOutput::modeChanged, this, &EglWaylandOutput::updateMode);
connect(m_waylandOutput, &WaylandOutput::modeChanged, this, &EglWaylandOutput::updateSize);
return true;
}
void EglWaylandOutput::updateSize(const QSize &size)
void EglWaylandOutput::updateSize()
{
wl_egl_window_resize(m_overlay, size.width(), size.height(), 0, 0);
}
void EglWaylandOutput::updateMode()
{
updateSize(m_waylandOutput->geometry().size());
const QSize nativeSize = m_waylandOutput->geometry().size() * m_waylandOutput->scale();
wl_egl_window_resize(m_overlay, nativeSize.width(), nativeSize.height(), 0, 0);
}
EglWaylandBackend::EglWaylandBackend(WaylandBackend *b)
@ -240,9 +236,7 @@ bool EglWaylandBackend::makeContextCurrent(EglWaylandOutput *output)
}
const QRect &v = output->m_waylandOutput->geometry();
//The output is in scaled coordinates
const qreal scale = 1;
const qreal scale = output->m_waylandOutput->scale();
const QSize overall = screens()->size();
glViewport(-v.x() * scale, (v.height() - overall.height() + v.y()) * scale,
@ -324,13 +318,15 @@ void EglWaylandBackend::aboutToStartPainting(int screenId, const QRegion &damage
void EglWaylandBackend::presentOnSurface(EglWaylandOutput *output, const QRegion &damage)
{
output->m_waylandOutput->surface()->setupFrameCallback();
Compositor::self()->aboutToSwapBuffers();
WaylandOutput *waylandOutput = output->m_waylandOutput;
Q_EMIT output->m_waylandOutput->outputChange(damage);
waylandOutput->surface()->setupFrameCallback();
waylandOutput->surface()->setScale(waylandOutput->scale());
Compositor::self()->aboutToSwapBuffers();
Q_EMIT waylandOutput->outputChange(damage);
if (supportsSwapBuffersWithDamage() && !output->m_damageHistory.isEmpty()) {
QVector<EGLint> rects = regionToRects(output->m_damageHistory.constFirst(), output->m_waylandOutput);
QVector<EGLint> rects = regionToRects(output->m_damageHistory.constFirst(), waylandOutput);
eglSwapBuffersWithDamageEXT(eglDisplay(), output->m_eglSurface,
rects.data(), rects.count()/4);
} else {

View file

@ -34,8 +34,7 @@ public:
~EglWaylandOutput() override = default;
bool init(EglWaylandBackend *backend);
void updateSize(const QSize &size);
void updateMode();
void updateSize();
private:
WaylandOutput *m_waylandOutput;

View file

@ -86,6 +86,7 @@ void WaylandQPainterOutput::present(const QRegion &damage)
auto s = m_waylandOutput->surface();
s->attachBuffer(m_buffer);
s->damage(damage);
s->setScale(m_waylandOutput->scale());
s->commit();
}
@ -104,9 +105,9 @@ void WaylandQPainterOutput::prepareRenderingFrame()
}
m_buffer.clear();
const QSize size(m_waylandOutput->geometry().size());
const QSize nativeSize(m_waylandOutput->geometry().size() * m_waylandOutput->scale());
m_buffer = m_pool->getBuffer(size, size.width() * 4);
m_buffer = m_pool->getBuffer(nativeSize, nativeSize.width() * 4);
if (!m_buffer) {
qCDebug(KWIN_WAYLAND_BACKEND) << "Did not get a new Buffer from Shm Pool";
m_backBuffer = QImage();
@ -116,7 +117,7 @@ void WaylandQPainterOutput::prepareRenderingFrame()
auto b = m_buffer.toStrongRef();
b->setUsed(true);
m_backBuffer = QImage(b->address(), size.width(), size.height(), QImage::Format_RGB32);
m_backBuffer = QImage(b->address(), nativeSize.width(), nativeSize.height(), QImage::Format_RGB32);
m_backBuffer.fill(Qt::transparent);
// qCDebug(KWIN_WAYLAND_BACKEND) << "Created a new back buffer for output surface" << m_waylandOutput->surface();
}

View file

@ -92,29 +92,30 @@ void WaylandCursor::installImage()
{
const QImage image = Cursors::self()->currentCursor()->image();
if (image.isNull() || image.size().isEmpty()) {
doInstallImage(nullptr, QSize());
doInstallImage(nullptr, QSize(), 1);
return;
}
auto buffer = m_backend->shmPool()->createBuffer(image).toStrongRef();
wl_buffer *imageBuffer = *buffer.data();
doInstallImage(imageBuffer, image.size());
doInstallImage(imageBuffer, image.size(), image.devicePixelRatio());
}
void WaylandCursor::doInstallImage(wl_buffer *image, const QSize &size)
void WaylandCursor::doInstallImage(wl_buffer *image, const QSize &size, qreal scale)
{
auto *pointer = m_backend->seat()->pointer();
if (!pointer || !pointer->isValid()) {
return;
}
pointer->setCursor(m_surface, image ? Cursors::self()->currentCursor()->hotspot() : QPoint());
drawSurface(image, size);
drawSurface(image, size, scale);
}
void WaylandCursor::drawSurface(wl_buffer *image, const QSize &size)
void WaylandCursor::drawSurface(wl_buffer *image, const QSize &size, qreal scale)
{
m_surface->attachBuffer(image);
m_surface->damage(QRect(QPoint(0,0), size));
m_surface->setScale(scale);
m_surface->damageBuffer(QRect(QPoint(0, 0), size));
m_surface->commit(Surface::CommitFlag::None);
m_backend->flush();
}
@ -161,7 +162,7 @@ void WaylandSubSurfaceCursor::createSubSurface()
m_subSurface->setMode(SubSurface::Mode::Desynchronized);
}
void WaylandSubSurfaceCursor::doInstallImage(wl_buffer *image, const QSize &size)
void WaylandSubSurfaceCursor::doInstallImage(wl_buffer *image, const QSize &size, qreal scale)
{
if (!image) {
delete m_subSurface;
@ -171,7 +172,7 @@ void WaylandSubSurfaceCursor::doInstallImage(wl_buffer *image, const QSize &size
createSubSurface();
// cursor position might have changed due to different cursor hot spot
move(input()->pointer()->pos());
drawSurface(image, size);
drawSurface(image, size, scale);
}
QPointF WaylandSubSurfaceCursor::absoluteToRelativePosition(const QPointF &position)
@ -496,11 +497,12 @@ WaylandBackend::~WaylandBackend()
void WaylandBackend::init()
{
connect(m_registry, &Registry::compositorAnnounced, this,
[this](quint32 name) {
m_compositor->setup(m_registry->bindCompositor(name, 1));
connect(m_registry, &Registry::compositorAnnounced, this, [this](quint32 name, quint32 version) {
if (version < 4) {
qFatal("wl_compositor version 4 or later is required");
}
);
m_compositor->setup(m_registry->bindCompositor(name, version));
});
connect(m_registry, &Registry::subCompositorAnnounced, this,
[this](quint32 name) {
m_subCompositor->setup(m_registry->bindSubCompositor(name, 1));

View file

@ -79,8 +79,8 @@ public:
protected:
void resetSurface();
virtual void doInstallImage(wl_buffer *image, const QSize &size);
void drawSurface(wl_buffer *image, const QSize &size);
virtual void doInstallImage(wl_buffer *image, const QSize &size, qreal scale);
void drawSurface(wl_buffer *image, const QSize &size, qreal scale);
KWayland::Client::Surface *surface() const {
return m_surface;
@ -108,7 +108,7 @@ public:
private:
void changeOutput(WaylandOutput *output);
void doInstallImage(wl_buffer *image, const QSize &size) override;
void doInstallImage(wl_buffer *image, const QSize &size, qreal scale) override;
void createSubSurface();
QPointF absoluteToRelativePosition(const QPointF &position);