2020-10-05 21:05:55 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
|
|
|
|
|
|
|
SPDX-FileCopyrightText: 2020 Xaver Hugl <xaver.hugl@gmail.com>
|
|
|
|
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef DRM_GPU_H
|
|
|
|
#define DRM_GPU_H
|
|
|
|
|
|
|
|
#include <qobject.h>
|
|
|
|
#include <QVector>
|
2021-02-19 11:59:43 +00:00
|
|
|
#include <QSocketNotifier>
|
2021-05-19 17:27:04 +00:00
|
|
|
#include <QPointer>
|
2021-11-22 10:43:28 +00:00
|
|
|
#include <QSize>
|
2020-10-05 21:05:55 +00:00
|
|
|
|
2020-10-16 13:11:23 +00:00
|
|
|
#include <epoxy/egl.h>
|
2021-11-22 13:00:59 +00:00
|
|
|
#include <sys/types.h>
|
2020-10-16 13:11:23 +00:00
|
|
|
|
2020-10-05 21:05:55 +00:00
|
|
|
struct gbm_device;
|
|
|
|
|
2021-02-05 18:45:34 +00:00
|
|
|
namespace KWaylandServer
|
|
|
|
{
|
|
|
|
class DrmLeaseDeviceV1Interface;
|
|
|
|
class DrmLeaseV1Interface;
|
|
|
|
}
|
|
|
|
|
2020-10-05 21:05:55 +00:00
|
|
|
namespace KWin
|
|
|
|
{
|
2020-11-27 19:57:24 +00:00
|
|
|
|
2020-10-05 21:05:55 +00:00
|
|
|
class DrmOutput;
|
2021-11-22 10:43:28 +00:00
|
|
|
class DrmObject;
|
2020-10-05 21:05:55 +00:00
|
|
|
class DrmCrtc;
|
|
|
|
class DrmConnector;
|
2021-11-22 10:43:28 +00:00
|
|
|
class DrmPlane;
|
2020-10-05 21:05:55 +00:00
|
|
|
class DrmBackend;
|
2021-11-10 12:26:34 +00:00
|
|
|
class EglGbmBackend;
|
2021-05-25 22:05:17 +00:00
|
|
|
class DrmPipeline;
|
2021-07-26 23:11:50 +00:00
|
|
|
class DrmAbstractOutput;
|
|
|
|
class DrmVirtualOutput;
|
2021-02-05 18:45:34 +00:00
|
|
|
class DrmLeaseOutput;
|
2020-11-27 19:57:24 +00:00
|
|
|
|
2020-10-05 21:05:55 +00:00
|
|
|
class DrmGpu : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
2021-04-30 07:05:49 +00:00
|
|
|
DrmGpu(DrmBackend *backend, const QString &devNode, int fd, dev_t deviceId);
|
2020-10-05 21:05:55 +00:00
|
|
|
~DrmGpu();
|
2020-11-27 19:57:24 +00:00
|
|
|
|
2021-09-22 11:26:19 +00:00
|
|
|
int fd() const;
|
|
|
|
dev_t deviceId() const;
|
|
|
|
QString devNode() const;
|
2020-11-27 19:57:24 +00:00
|
|
|
|
2021-09-22 11:26:19 +00:00
|
|
|
bool atomicModeSetting() const;
|
|
|
|
bool addFB2ModifiersSupported() const;
|
2021-10-14 15:25:13 +00:00
|
|
|
bool isNVidia() const;
|
2021-09-22 11:26:19 +00:00
|
|
|
bool isFormatSupported(uint32_t drmFormat) const;
|
|
|
|
gbm_device *gbmDevice() const;
|
|
|
|
EGLDisplay eglDisplay() const;
|
2021-11-10 12:26:34 +00:00
|
|
|
EglGbmBackend *eglBackend() const;
|
2021-09-22 11:26:19 +00:00
|
|
|
DrmBackend *platform() const;
|
Introduce RenderLoop
At the moment, our frame scheduling infrastructure is still heavily
based on Xinerama-style rendering. Specifically, we assume that painting
is driven by a single timer, etc.
This change introduces a new type - RenderLoop. Its main purpose is to
drive compositing on a specific output, or in case of X11, on the
overlay window.
With RenderLoop, compositing is synchronized to vblank events. It
exposes the last and the next estimated presentation timestamp. The
expected presentation timestamp can be used by effects to ensure that
animations are synchronized with the upcoming vblank event.
On Wayland, every outputs has its own render loop. On X11, per screen
rendering is not possible, therefore the platform exposes the render
loop for the overlay window. Ideally, the Scene has to expose the
RenderLoop, but as the first step towards better compositing scheduling
it's good as is for the time being.
The RenderLoop tries to minimize the latency by delaying compositing as
close as possible to the next vblank event. One tricky thing about it is
that if compositing is too close to the next vblank event, animations
may become a little bit choppy. However, increasing the latency reduces
the choppiness.
Given that, there is no any "silver bullet" solution for the choppiness
issue, a new option has been added in the Compositing KCM to specify the
amount of latency. By default, it's "Medium," but if a user is not
satisfied with the upstream default, they can tweak it.
2020-11-19 08:52:29 +00:00
|
|
|
/**
|
|
|
|
* Returns the clock from which presentation timestamps are sourced. The returned value
|
|
|
|
* can be either CLOCK_MONOTONIC or CLOCK_REALTIME.
|
|
|
|
*/
|
|
|
|
clockid_t presentationClock() const;
|
|
|
|
|
2021-09-22 11:26:19 +00:00
|
|
|
QVector<DrmAbstractOutput*> outputs() const;
|
2021-05-25 22:05:17 +00:00
|
|
|
const QVector<DrmPipeline*> pipelines() const;
|
2021-09-28 08:29:56 +00:00
|
|
|
bool testPendingConfiguration();
|
2021-02-22 18:17:23 +00:00
|
|
|
|
2021-09-22 11:26:19 +00:00
|
|
|
void setEglDisplay(EGLDisplay display);
|
2021-11-10 12:26:34 +00:00
|
|
|
void setEglBackend(EglGbmBackend *eglBackend);
|
2021-09-22 11:26:19 +00:00
|
|
|
|
|
|
|
bool updateOutputs();
|
2021-10-05 17:06:28 +00:00
|
|
|
|
|
|
|
enum VirtualOutputMode { Placeholder, Full };
|
|
|
|
DrmVirtualOutput *createVirtualOutput(const QString &name, const QSize &size, double scale, VirtualOutputMode mode);
|
2021-07-26 23:11:50 +00:00
|
|
|
void removeVirtualOutput(DrmVirtualOutput *output);
|
|
|
|
|
2021-10-08 08:52:01 +00:00
|
|
|
bool needsModeset() const;
|
|
|
|
bool maybeModeset();
|
|
|
|
|
2020-10-05 21:05:55 +00:00
|
|
|
Q_SIGNALS:
|
2021-07-26 23:11:50 +00:00
|
|
|
void outputAdded(DrmAbstractOutput *output);
|
|
|
|
void outputRemoved(DrmAbstractOutput *output);
|
|
|
|
void outputEnabled(DrmAbstractOutput *output);
|
|
|
|
void outputDisabled(DrmAbstractOutput *output);
|
2020-11-27 19:57:24 +00:00
|
|
|
|
2020-10-05 21:05:55 +00:00
|
|
|
private:
|
2021-02-19 13:00:49 +00:00
|
|
|
void dispatchEvents();
|
2020-10-05 21:05:55 +00:00
|
|
|
DrmOutput *findOutput(quint32 connector);
|
2021-02-05 18:45:34 +00:00
|
|
|
DrmLeaseOutput *findLeaseOutput(quint32 connector);
|
2021-04-27 11:49:53 +00:00
|
|
|
void removeOutput(DrmOutput *output);
|
2021-02-05 18:45:34 +00:00
|
|
|
void removeLeaseOutput(DrmLeaseOutput *output);
|
2021-08-07 18:06:40 +00:00
|
|
|
void initDrmResources();
|
2021-11-22 10:43:28 +00:00
|
|
|
void waitIdle();
|
2021-08-07 18:06:40 +00:00
|
|
|
|
2021-09-28 08:29:56 +00:00
|
|
|
bool checkCrtcAssignment(QVector<DrmConnector*> connectors, QVector<DrmCrtc*> crtcs);
|
2021-10-08 09:22:02 +00:00
|
|
|
QVector<DrmObject*> unusedObjects() const;
|
2020-11-27 19:57:24 +00:00
|
|
|
|
2021-02-05 18:45:34 +00:00
|
|
|
void handleLeaseRequest(KWaylandServer::DrmLeaseV1Interface *leaseRequest);
|
|
|
|
void handleLeaseRevoked(KWaylandServer::DrmLeaseV1Interface *lease);
|
|
|
|
|
2021-10-08 08:52:01 +00:00
|
|
|
static void pageFlipHandler(int fd, unsigned int sequence, unsigned int sec, unsigned int usec, unsigned int crtc_id, void *user_data);
|
|
|
|
|
2020-10-05 21:05:55 +00:00
|
|
|
const int m_fd;
|
2021-04-28 18:30:16 +00:00
|
|
|
const dev_t m_deviceId;
|
2021-09-22 11:26:19 +00:00
|
|
|
const QString m_devNode;
|
2020-10-05 21:05:55 +00:00
|
|
|
bool m_atomicModeSetting;
|
2021-09-22 11:26:19 +00:00
|
|
|
bool m_addFB2ModifiersSupported = false;
|
2021-10-14 15:25:13 +00:00
|
|
|
bool m_isNVidia;
|
2021-09-22 11:26:19 +00:00
|
|
|
clockid_t m_presentationClock;
|
2020-10-05 21:05:55 +00:00
|
|
|
gbm_device* m_gbmDevice;
|
2020-10-16 13:11:23 +00:00
|
|
|
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
|
2021-11-10 12:26:34 +00:00
|
|
|
QPointer<EglGbmBackend> m_eglBackend;
|
2021-09-22 11:26:19 +00:00
|
|
|
DrmBackend* const m_platform;
|
2020-11-27 19:57:24 +00:00
|
|
|
|
2020-10-05 21:05:55 +00:00
|
|
|
QVector<DrmPlane*> m_planes;
|
|
|
|
QVector<DrmCrtc*> m_crtcs;
|
|
|
|
QVector<DrmConnector*> m_connectors;
|
2021-10-08 09:22:02 +00:00
|
|
|
QVector<DrmObject*> m_allObjects;
|
2021-05-25 22:05:17 +00:00
|
|
|
QVector<DrmPipeline*> m_pipelines;
|
2021-08-07 18:06:40 +00:00
|
|
|
|
2021-07-26 23:11:50 +00:00
|
|
|
QVector<DrmOutput*> m_drmOutputs;
|
|
|
|
QVector<DrmAbstractOutput*> m_outputs;
|
2021-02-05 18:45:34 +00:00
|
|
|
QVector<DrmLeaseOutput*> m_leaseOutputs;
|
|
|
|
KWaylandServer::DrmLeaseDeviceV1Interface *m_leaseDevice = nullptr;
|
2021-09-22 11:26:19 +00:00
|
|
|
|
|
|
|
QSocketNotifier *m_socketNotifier = nullptr;
|
|
|
|
QSize m_cursorSize;
|
2020-10-05 21:05:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // DRM_GPU_H
|