Handle session deactivate and restore in DRM backend

* blocks compositor while session is inactive
* prevents page flips while session is inactive
* restores modes when going to inactive
* hides cursor when going to inactive
* blanks screens when going active
* shows cursor again when going active
* triggers a repaint when going active
This commit is contained in:
Martin Gräßlin 2015-04-15 18:26:25 +02:00
parent 3a9adcac91
commit 8278ae8487
3 changed files with 88 additions and 19 deletions

View file

@ -94,7 +94,58 @@ void DrmBackend::init()
} else {
connect(logind, &LogindIntegration::connectedChanged, this, takeControl);
}
VirtualTerminal::create(this);
auto v = VirtualTerminal::create(this);
connect(v, &VirtualTerminal::activeChanged, this, &DrmBackend::activate);
}
void DrmBackend::activate(bool active)
{
if (active) {
reactivate();
} else {
deactivate();
}
}
void DrmBackend::reactivate()
{
if (m_active) {
return;
}
m_active = true;
DrmBuffer *c = m_cursor[(m_cursorIndex + 1) % 2];
const QPoint cp = Cursor::pos() - softwareCursorHotspot();
for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) {
DrmOutput *o = *it;
o->pageFlipped();
o->blank();
o->showCursor(c);
o->moveCursor(cp);
}
// restart compositor
m_pageFlipsPending = 0;
if (Compositor *compositor = Compositor::self()) {
compositor->bufferSwapComplete();
compositor->addRepaintFull();
}
}
void DrmBackend::deactivate()
{
if (!m_active) {
return;
}
// block compositor
if (m_pageFlipsPending == 0 && Compositor::self()) {
Compositor::self()->aboutToSwapBuffers();
}
// hide cursor and disable
for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) {
DrmOutput *o = *it;
o->hideCursor();
o->restoreSaved();
}
m_active = false;
}
void DrmBackend::pageFlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
@ -117,6 +168,7 @@ void DrmBackend::pageFlipHandler(int fd, unsigned int frame, unsigned int sec, u
void DrmBackend::openDrm()
{
connect(LogindIntegration::self(), &LogindIntegration::sessionActiveChanged, this, &DrmBackend::activate);
VirtualTerminal::self()->init();
UdevDevice::Ptr device = m_udev->primaryGpu();
if (!device) {
@ -129,9 +181,13 @@ void DrmBackend::openDrm()
return;
}
m_fd = fd;
m_active = true;
QSocketNotifier *notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
connect(notifier, &QSocketNotifier::activated, this,
[this] {
if (!VirtualTerminal::self()->isActive()) {
return;
}
drmEventContext e;
memset(&e, 0, sizeof e);
e.version = DRM_EVENT_CONTEXT_VERSION;
@ -331,10 +387,6 @@ DrmOutput::DrmOutput(DrmBackend *backend)
DrmOutput::~DrmOutput()
{
hideCursor();
if (!m_savedCrtc.isNull()) {
drmModeSetCrtc(m_backend->fd(), m_savedCrtc->crtc_id, m_savedCrtc->buffer_id,
m_savedCrtc->x, m_savedCrtc->y, &m_connector, 1, &m_savedCrtc->mode);
}
cleanupBlackBuffer();
}
@ -343,6 +395,14 @@ void DrmOutput::hideCursor()
drmModeSetCursor(m_backend->fd(), m_crtcId, 0, 0, 0);
}
void DrmOutput::restoreSaved()
{
if (!m_savedCrtc.isNull()) {
drmModeSetCrtc(m_backend->fd(), m_savedCrtc->crtc_id, m_savedCrtc->buffer_id,
m_savedCrtc->x, m_savedCrtc->y, &m_connector, 1, &m_savedCrtc->mode);
}
}
void DrmOutput::showCursor(DrmBuffer *c)
{
const QSize &s = c->size();
@ -365,6 +425,10 @@ bool DrmOutput::present(DrmBuffer *buffer)
if (!buffer || buffer->bufferId() == 0) {
return false;
}
if (!VirtualTerminal::self()->isActive()) {
m_currentBuffer = buffer;
return false;
}
if (m_currentBuffer) {
return false;
}
@ -374,6 +438,9 @@ bool DrmOutput::present(DrmBuffer *buffer)
void DrmOutput::pageFlipped()
{
if (!m_currentBuffer) {
return;
}
m_currentBuffer->releaseGbm();
m_currentBuffer = nullptr;
cleanupBlackBuffer();
@ -390,9 +457,16 @@ void DrmOutput::cleanupBlackBuffer()
void DrmOutput::init()
{
m_savedCrtc.reset(drmModeGetCrtc(m_backend->fd(), m_crtcId));
m_blackBuffer = m_backend->createBuffer(size());
m_blackBuffer->map();
m_blackBuffer->image()->fill(Qt::black);
blank();
}
void DrmOutput::blank()
{
if (!m_blackBuffer) {
m_blackBuffer = m_backend->createBuffer(size());
m_blackBuffer->map();
m_blackBuffer->image()->fill(Qt::black);
}
drmModeSetCrtc(m_backend->fd(), m_crtcId, m_blackBuffer->bufferId(), 0, 0, &m_connector, 1, &m_mode);
}

View file

@ -65,6 +65,9 @@ Q_SIGNALS:
private:
static void pageFlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data);
void openDrm();
void activate(bool active);
void reactivate();
void deactivate();
void queryResources();
void setCursor();
void updateCursor();
@ -78,6 +81,7 @@ private:
DrmBuffer *m_cursor[2];
int m_cursorIndex = 0;
int m_pageFlipsPending = 0;
bool m_active = false;
};
class DrmOutput
@ -90,6 +94,8 @@ public:
bool present(DrmBuffer *buffer);
void pageFlipped();
void init();
void restoreSaved();
void blank();
QSize size() const;

View file

@ -351,17 +351,6 @@ DrmQPainterBackend::DrmQPainterBackend(DrmBackend *backend)
m_buffer[1]->map();
m_buffer[0]->image()->fill(Qt::black);
m_buffer[1]->image()->fill(Qt::black);
connect(VirtualTerminal::self(), &VirtualTerminal::activeChanged, this,
[this] (bool active) {
if (active) {
Compositor::self()->bufferSwapComplete();
Compositor::self()->addRepaintFull();
} else {
Compositor::self()->aboutToSwapBuffers();
}
}
);
}
DrmQPainterBackend::~DrmQPainterBackend()