Changeset View
Changeset View
Standalone View
Standalone View
plugins/platforms/drm/drm_output.cpp
Show First 20 Lines • Show All 56 Lines • ▼ Show 20 Line(s) | 56 | DrmOutput::DrmOutput(DrmBackend *backend) | |||
---|---|---|---|---|---|
57 | : QObject() | 57 | : QObject() | ||
58 | , m_backend(backend) | 58 | , m_backend(backend) | ||
59 | { | 59 | { | ||
60 | } | 60 | } | ||
61 | 61 | | |||
62 | DrmOutput::~DrmOutput() | 62 | DrmOutput::~DrmOutput() | ||
63 | { | 63 | { | ||
64 | hideCursor(); | 64 | hideCursor(); | ||
65 | cleanupBlackBuffer(); | 65 | m_crtc->blank(); | ||
66 | delete m_crtc; | | |||
67 | delete m_conn; | | |||
68 | delete m_waylandOutput.data(); | 66 | delete m_waylandOutput.data(); | ||
69 | delete m_waylandOutputDevice.data(); | 67 | delete m_waylandOutputDevice.data(); | ||
70 | } | 68 | } | ||
71 | 69 | | |||
72 | void DrmOutput::cleanup() | 70 | void DrmOutput::releaseGbm() | ||
73 | { | 71 | { | ||
74 | if (m_currentBuffer) { | 72 | if (DrmBuffer *b = m_crtc->current()) { | ||
75 | m_currentBuffer->releaseGbm(); | 73 | b->releaseGbm(); | ||
76 | } | | |||
77 | if (m_nextBuffer) { | | |||
78 | m_nextBuffer->releaseGbm(); | | |||
79 | } | 74 | } | ||
80 | if (m_primaryPlane) { | 75 | if (m_primaryPlane) { | ||
81 | if (m_primaryPlane->current()) { | 76 | if (m_primaryPlane->current()) { | ||
82 | m_primaryPlane->current()->releaseGbm(); | 77 | m_primaryPlane->current()->releaseGbm(); | ||
83 | } | 78 | } | ||
84 | if (m_primaryPlane->next()) { | | |||
85 | m_primaryPlane->next()->releaseGbm(); | | |||
86 | } | | |||
87 | } | 79 | } | ||
88 | } | 80 | } | ||
89 | 81 | | |||
90 | void DrmOutput::hideCursor() | 82 | void DrmOutput::hideCursor() | ||
91 | { | 83 | { | ||
92 | drmModeSetCursor(m_backend->fd(), m_crtcId, 0, 0, 0); | 84 | drmModeSetCursor(m_backend->fd(), m_crtc->id(), 0, 0, 0); | ||
93 | } | | |||
94 | | ||||
95 | void DrmOutput::restoreSaved() | | |||
96 | { | | |||
97 | if (!m_savedCrtc.isNull()) { | | |||
98 | drmModeSetCrtc(m_backend->fd(), m_savedCrtc->crtc_id, m_savedCrtc->buffer_id, | | |||
99 | m_savedCrtc->x, m_savedCrtc->y, &m_connector, 1, &m_savedCrtc->mode); | | |||
100 | } | | |||
101 | } | 85 | } | ||
102 | 86 | | |||
103 | void DrmOutput::showCursor(DrmBuffer *c) | 87 | void DrmOutput::showCursor(DrmBuffer *c) | ||
104 | { | 88 | { | ||
105 | const QSize &s = c->size(); | 89 | const QSize &s = c->size(); | ||
106 | drmModeSetCursor(m_backend->fd(), m_crtcId, c->handle(), s.width(), s.height()); | 90 | drmModeSetCursor(m_backend->fd(), m_crtc->id(), c->handle(), s.width(), s.height()); | ||
107 | } | 91 | } | ||
108 | 92 | | |||
109 | void DrmOutput::moveCursor(const QPoint &globalPos) | 93 | void DrmOutput::moveCursor(const QPoint &globalPos) | ||
110 | { | 94 | { | ||
111 | const QPoint p = globalPos - m_globalPos; | 95 | const QPoint p = globalPos - m_globalPos; | ||
112 | drmModeMoveCursor(m_backend->fd(), m_crtcId, p.x(), p.y()); | 96 | drmModeMoveCursor(m_backend->fd(), m_crtc->id(), p.x(), p.y()); | ||
113 | } | 97 | } | ||
114 | 98 | | |||
115 | QSize DrmOutput::size() const | 99 | QSize DrmOutput::size() const | ||
116 | { | 100 | { | ||
117 | return QSize(m_mode.hdisplay, m_mode.vdisplay); | 101 | return QSize(m_mode.hdisplay, m_mode.vdisplay); | ||
118 | } | 102 | } | ||
119 | 103 | | |||
120 | QRect DrmOutput::geometry() const | 104 | QRect DrmOutput::geometry() const | ||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Line(s) | 165 | { | |||
182 | initEdid(connector); | 166 | initEdid(connector); | ||
183 | initDpms(connector); | 167 | initDpms(connector); | ||
184 | initUuid(); | 168 | initUuid(); | ||
185 | if (m_backend->atomicModeSetting()) { | 169 | if (m_backend->atomicModeSetting()) { | ||
186 | if (!initPrimaryPlane()) { | 170 | if (!initPrimaryPlane()) { | ||
187 | return false; | 171 | return false; | ||
188 | } | 172 | } | ||
189 | } | 173 | } | ||
190 | m_savedCrtc.reset(drmModeGetCrtc(m_backend->fd(), m_crtcId)); | 174 | if (!m_crtc->blank()) { | ||
191 | if (!blank()) { | | |||
192 | return false; | 175 | return false; | ||
193 | } | 176 | } | ||
194 | setDpms(DpmsMode::On); | 177 | setDpms(DpmsMode::On); | ||
195 | if (!m_waylandOutput.isNull()) { | 178 | if (!m_waylandOutput.isNull()) { | ||
196 | delete m_waylandOutput.data(); | 179 | delete m_waylandOutput.data(); | ||
197 | m_waylandOutput.clear(); | 180 | m_waylandOutput.clear(); | ||
198 | } | 181 | } | ||
199 | m_waylandOutput = waylandServer()->display()->createOutput(); | 182 | m_waylandOutput = waylandServer()->display()->createOutput(); | ||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Line(s) | |||||
301 | qCDebug(KWIN_DRM) << "Created OutputDevice"; | 284 | qCDebug(KWIN_DRM) << "Created OutputDevice"; | ||
302 | m_waylandOutputDevice->create(); | 285 | m_waylandOutputDevice->create(); | ||
303 | return true; | 286 | return true; | ||
304 | } | 287 | } | ||
305 | 288 | | |||
306 | void DrmOutput::initUuid() | 289 | void DrmOutput::initUuid() | ||
307 | { | 290 | { | ||
308 | QCryptographicHash hash(QCryptographicHash::Md5); | 291 | QCryptographicHash hash(QCryptographicHash::Md5); | ||
309 | hash.addData(QByteArray::number(m_connector)); | 292 | hash.addData(QByteArray::number(m_conn->id())); | ||
310 | hash.addData(m_edid.eisaId); | 293 | hash.addData(m_edid.eisaId); | ||
311 | hash.addData(m_edid.monitorName); | 294 | hash.addData(m_edid.monitorName); | ||
312 | hash.addData(m_edid.serialNumber); | 295 | hash.addData(m_edid.serialNumber); | ||
313 | m_uuid = hash.result().toHex().left(10); | 296 | m_uuid = hash.result().toHex().left(10); | ||
314 | } | 297 | } | ||
315 | 298 | | |||
316 | bool DrmOutput::isCurrentMode(const drmModeModeInfo *mode) const | 299 | bool DrmOutput::isCurrentMode(const drmModeModeInfo *mode) const | ||
317 | { | 300 | { | ||
▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Line(s) | 484 | if (p->type() != DrmPlane::TypeIndex::Primary) { | |||
502 | continue; | 485 | continue; | ||
503 | } | 486 | } | ||
504 | if (p->output()) { // Plane already has an output | 487 | if (p->output()) { // Plane already has an output | ||
505 | continue; | 488 | continue; | ||
506 | } | 489 | } | ||
507 | if (m_primaryPlane) { // Output already has a primary plane | 490 | if (m_primaryPlane) { // Output already has a primary plane | ||
508 | continue; | 491 | continue; | ||
509 | } | 492 | } | ||
510 | if (!p->isCrtcSupported(m_crtcId)) { | 493 | if (!p->isCrtcSupported(m_crtc->id())) { | ||
511 | continue; | 494 | continue; | ||
512 | } | 495 | } | ||
513 | p->setOutput(this); | 496 | p->setOutput(this); | ||
514 | m_primaryPlane = p; | 497 | m_primaryPlane = p; | ||
515 | qCDebug(KWIN_DRM) << "Initialized primary plane" << p->id() << "on CRTC" << m_crtcId; | 498 | qCDebug(KWIN_DRM) << "Initialized primary plane" << p->id() << "on CRTC" << m_crtc->id(); | ||
516 | return true; | 499 | return true; | ||
517 | } | 500 | } | ||
518 | qCCritical(KWIN_DRM) << "Failed to initialize primary plane."; | 501 | qCCritical(KWIN_DRM) << "Failed to initialize primary plane."; | ||
519 | return false; | 502 | return false; | ||
520 | } | 503 | } | ||
521 | 504 | | |||
522 | bool DrmOutput::initCursorPlane() // TODO: Add call in init (but needs layer support in general first) | 505 | bool DrmOutput::initCursorPlane() // TODO: Add call in init (but needs layer support in general first) | ||
523 | { | 506 | { | ||
524 | for (int i = 0; i < m_backend->planes().size(); ++i) { | 507 | for (int i = 0; i < m_backend->planes().size(); ++i) { | ||
525 | DrmPlane* p = m_backend->planes()[i]; | 508 | DrmPlane* p = m_backend->planes()[i]; | ||
526 | if (!p) { | 509 | if (!p) { | ||
527 | continue; | 510 | continue; | ||
528 | } | 511 | } | ||
529 | if (p->type() != DrmPlane::TypeIndex::Cursor) { | 512 | if (p->type() != DrmPlane::TypeIndex::Cursor) { | ||
530 | continue; | 513 | continue; | ||
531 | } | 514 | } | ||
532 | if (p->output()) { // Plane already has an output | 515 | if (p->output()) { // Plane already has an output | ||
533 | continue; | 516 | continue; | ||
534 | } | 517 | } | ||
535 | if (m_cursorPlane) { // Output already has a cursor plane | 518 | if (m_cursorPlane) { // Output already has a cursor plane | ||
536 | continue; | 519 | continue; | ||
537 | } | 520 | } | ||
538 | if (!p->isCrtcSupported(m_crtcId)) { | 521 | if (!p->isCrtcSupported(m_crtc->id())) { | ||
539 | continue; | 522 | continue; | ||
540 | } | 523 | } | ||
541 | p->setOutput(this); | 524 | p->setOutput(this); | ||
542 | m_cursorPlane = p; | 525 | m_cursorPlane = p; | ||
543 | qCDebug(KWIN_DRM) << "Initialized cursor plane" << p->id() << "on CRTC" << m_crtcId; | 526 | qCDebug(KWIN_DRM) << "Initialized cursor plane" << p->id() << "on CRTC" << m_crtc->id(); | ||
544 | return true; | 527 | return true; | ||
545 | } | 528 | } | ||
546 | return false; | 529 | return false; | ||
547 | } | 530 | } | ||
548 | 531 | | |||
549 | void DrmOutput::initDpms(drmModeConnector *connector) | 532 | void DrmOutput::initDpms(drmModeConnector *connector) | ||
550 | { | 533 | { | ||
551 | for (int i = 0; i < connector->count_props; ++i) { | 534 | for (int i = 0; i < connector->count_props; ++i) { | ||
Show All 17 Lines | 551 | if (mode == m_dpmsMode) { | |||
569 | qCDebug(KWIN_DRM) << "New DPMS mode equals old mode. DPMS unchanged."; | 552 | qCDebug(KWIN_DRM) << "New DPMS mode equals old mode. DPMS unchanged."; | ||
570 | return; | 553 | return; | ||
571 | } | 554 | } | ||
572 | 555 | | |||
573 | if (m_backend->atomicModeSetting()) { | 556 | if (m_backend->atomicModeSetting()) { | ||
574 | drmModeAtomicReq *req = drmModeAtomicAlloc(); | 557 | drmModeAtomicReq *req = drmModeAtomicAlloc(); | ||
575 | 558 | | |||
576 | if (atomicReqModesetPopulate(req, mode == DpmsMode::On) == DrmObject::AtomicReturn::Error) { | 559 | if (atomicReqModesetPopulate(req, mode == DpmsMode::On) == DrmObject::AtomicReturn::Error) { | ||
577 | qCWarning(KWIN_DRM) << "Failed to populate atomic request for output" << m_crtcId; | 560 | qCWarning(KWIN_DRM) << "Failed to populate atomic request for output" << m_crtc->id(); | ||
578 | return; | 561 | return; | ||
579 | } | 562 | } | ||
580 | if (drmModeAtomicCommit(m_backend->fd(), req, DRM_MODE_ATOMIC_ALLOW_MODESET, this)) { | 563 | if (drmModeAtomicCommit(m_backend->fd(), req, DRM_MODE_ATOMIC_ALLOW_MODESET, this)) { | ||
581 | qCWarning(KWIN_DRM) << "Failed to commit atomic request for output" << m_crtcId; | 564 | qCWarning(KWIN_DRM) << "Failed to commit atomic request for output" << m_crtc->id(); | ||
582 | } else { | 565 | } else { | ||
583 | qCDebug(KWIN_DRM) << "DPMS set for output" << m_crtcId; | 566 | qCDebug(KWIN_DRM) << "DPMS set for output" << m_crtc->id(); | ||
584 | } | 567 | } | ||
585 | drmModeAtomicFree(req); | 568 | drmModeAtomicFree(req); | ||
586 | } else { | 569 | } else { | ||
587 | if (drmModeConnectorSetProperty(m_backend->fd(), m_connector, m_dpms->prop_id, uint64_t(mode)) < 0) { | 570 | if (drmModeConnectorSetProperty(m_backend->fd(), m_conn->id(), m_dpms->prop_id, uint64_t(mode)) < 0) { | ||
588 | qCWarning(KWIN_DRM) << "Setting DPMS failed"; | 571 | qCWarning(KWIN_DRM) << "Setting DPMS failed"; | ||
589 | return; | 572 | return; | ||
590 | } | 573 | } | ||
591 | } | 574 | } | ||
592 | 575 | | |||
593 | m_dpmsMode = mode; | 576 | m_dpmsMode = mode; | ||
594 | if (m_waylandOutput) { | 577 | if (m_waylandOutput) { | ||
595 | m_waylandOutput->setDpmsMode(toWaylandDpmsMode(m_dpmsMode)); | 578 | m_waylandOutput->setDpmsMode(toWaylandDpmsMode(m_dpmsMode)); | ||
596 | } | 579 | } | ||
597 | emit dpmsChanged(); | 580 | emit dpmsChanged(); | ||
598 | if (m_dpmsMode != DpmsMode::On) { | 581 | if (m_dpmsMode != DpmsMode::On) { | ||
599 | m_backend->outputWentOff(); | 582 | m_backend->outputWentOff(); | ||
600 | } else { | 583 | } else { | ||
601 | m_backend->checkOutputsAreOn(); | 584 | m_backend->checkOutputsAreOn(); | ||
602 | blank(); | 585 | m_crtc->blank(); | ||
603 | if (Compositor *compositor = Compositor::self()) { | 586 | if (Compositor *compositor = Compositor::self()) { | ||
604 | compositor->addRepaintFull(); | 587 | compositor->addRepaintFull(); | ||
605 | } | 588 | } | ||
606 | } | 589 | } | ||
607 | } | 590 | } | ||
608 | 591 | | |||
609 | QString DrmOutput::name() const | 592 | QString DrmOutput::name() const | ||
610 | { | 593 | { | ||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Line(s) | 658 | if (m_changeset->scaleChanged()) { | |||
677 | m_waylandOutputDevice->setScale(m_changeset->scale()); | 660 | m_waylandOutputDevice->setScale(m_changeset->scale()); | ||
678 | // FIXME: implement for wl_output | 661 | // FIXME: implement for wl_output | ||
679 | } | 662 | } | ||
680 | return true; | 663 | return true; | ||
681 | } | 664 | } | ||
682 | 665 | | |||
683 | void DrmOutput::pageFlipped() | 666 | void DrmOutput::pageFlipped() | ||
684 | { | 667 | { | ||
668 | if (!m_crtc) { | ||||
669 | return; | ||||
670 | } | ||||
685 | if (m_backend->atomicModeSetting()){ | 671 | if (m_backend->atomicModeSetting()){ | ||
686 | foreach (DrmPlane *p, m_planesFlipList) { | 672 | foreach (DrmPlane *p, m_planesFlipList) { | ||
687 | pageFlippedBufferRemover(p->current(), p->next()); | 673 | pageFlippedBufferRemover(p->current(), p->next()); | ||
688 | p->setCurrent(p->next()); | 674 | p->setCurrent(p->next()); | ||
689 | p->setNext(nullptr); | 675 | p->setNext(nullptr); | ||
690 | } | 676 | } | ||
691 | m_planesFlipList.clear(); | 677 | m_planesFlipList.clear(); | ||
692 | 678 | | |||
693 | } else { | 679 | } else { | ||
694 | if (!m_nextBuffer) { | 680 | if (!m_crtc->next()) { | ||
695 | // on manual vt switch | 681 | // on manual vt switch | ||
696 | if (m_currentBuffer) { | 682 | if (DrmBuffer *b = m_crtc->current()) { | ||
697 | m_currentBuffer->releaseGbm(); | 683 | b->releaseGbm(); | ||
698 | } | 684 | } | ||
699 | return; | 685 | return; | ||
700 | } | 686 | } | ||
701 | pageFlippedBufferRemover(m_currentBuffer, m_nextBuffer); | 687 | m_crtc->flipBuffer(); | ||
702 | m_currentBuffer = m_nextBuffer; | | |||
703 | m_nextBuffer = nullptr; | | |||
704 | } | 688 | } | ||
705 | cleanupBlackBuffer(); | | |||
706 | } | 689 | } | ||
707 | 690 | | |||
708 | void DrmOutput::pageFlippedBufferRemover(DrmBuffer *oldbuffer, DrmBuffer *newbuffer) | 691 | void DrmOutput::pageFlippedBufferRemover(DrmBuffer *oldbuffer, DrmBuffer *newbuffer) | ||
709 | { | 692 | { | ||
710 | if (oldbuffer && oldbuffer->deleteAfterPageFlip() && oldbuffer != newbuffer) { | 693 | if (oldbuffer && oldbuffer->deleteAfterPageFlip() && oldbuffer != newbuffer) { | ||
711 | delete oldbuffer; | 694 | delete oldbuffer; | ||
712 | } | 695 | } | ||
713 | } | 696 | } | ||
714 | 697 | | |||
715 | void DrmOutput::cleanupBlackBuffer() | | |||
716 | { | | |||
717 | if (m_blackBuffer) { | | |||
718 | delete m_blackBuffer; | | |||
719 | m_blackBuffer = nullptr; | | |||
720 | } | | |||
721 | } | | |||
722 | | ||||
723 | bool DrmOutput::blank() | | |||
724 | { | | |||
725 | if (!m_blackBuffer) { | | |||
726 | m_blackBuffer = m_backend->createBuffer(size()); | | |||
727 | if (!m_blackBuffer->map()) { | | |||
728 | cleanupBlackBuffer(); | | |||
729 | return false; | | |||
730 | } | | |||
731 | m_blackBuffer->image()->fill(Qt::black); | | |||
732 | } | | |||
733 | // TODO: Do this atomically | | |||
734 | return setModeLegacy(m_blackBuffer); | | |||
735 | } | | |||
736 | | ||||
737 | bool DrmOutput::present(DrmBuffer *buffer) | 698 | bool DrmOutput::present(DrmBuffer *buffer) | ||
738 | { | 699 | { | ||
739 | if (!buffer || buffer->bufferId() == 0) { | 700 | if (!buffer || buffer->bufferId() == 0) { | ||
740 | return false; | 701 | return false; | ||
741 | } | 702 | } | ||
742 | if (m_backend->atomicModeSetting()) { | 703 | if (m_backend->atomicModeSetting()) { | ||
743 | return presentAtomically(buffer); | 704 | return presentAtomically(buffer); | ||
744 | } else { | 705 | } else { | ||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Line(s) | 711 | { | |||
847 | 808 | | |||
848 | drmModeAtomicFree(req); | 809 | drmModeAtomicFree(req); | ||
849 | return true; | 810 | return true; | ||
850 | } | 811 | } | ||
851 | 812 | | |||
852 | 813 | | |||
853 | bool DrmOutput::presentLegacy(DrmBuffer *buffer) | 814 | bool DrmOutput::presentLegacy(DrmBuffer *buffer) | ||
854 | { | 815 | { | ||
855 | if (m_nextBuffer) { | 816 | if (m_crtc->next()) { | ||
856 | return false; | 817 | return false; | ||
857 | } | 818 | } | ||
858 | if (!LogindIntegration::self()->isActiveSession()) { | 819 | if (!LogindIntegration::self()->isActiveSession()) { | ||
859 | m_nextBuffer = buffer; | 820 | m_crtc->setNext(buffer); | ||
860 | return false; | 821 | return false; | ||
861 | } | 822 | } | ||
862 | if (m_dpmsMode != DpmsMode::On) { | 823 | if (m_dpmsMode != DpmsMode::On) { | ||
863 | return false; | 824 | return false; | ||
864 | } | 825 | } | ||
865 | 826 | | |||
866 | // Do we need to set a new mode first? | 827 | // Do we need to set a new mode first? | ||
867 | if (m_lastStride != buffer->stride() || m_lastGbm != buffer->isGbm()){ | 828 | if (m_lastStride != buffer->stride() || m_lastGbm != buffer->isGbm()){ | ||
868 | if (!setModeLegacy(buffer)) | 829 | if (!setModeLegacy(buffer)) | ||
869 | return false; | 830 | return false; | ||
870 | } | 831 | } | ||
871 | int errno_save = 0; | 832 | int errno_save = 0; | ||
872 | const bool ok = drmModePageFlip(m_backend->fd(), m_crtcId, buffer->bufferId(), DRM_MODE_PAGE_FLIP_EVENT, this) == 0; | 833 | const bool ok = drmModePageFlip(m_backend->fd(), m_crtc->id(), buffer->bufferId(), DRM_MODE_PAGE_FLIP_EVENT, this) == 0; | ||
873 | if (ok) { | 834 | if (ok) { | ||
874 | m_nextBuffer = buffer; | 835 | m_crtc->setNext(buffer); | ||
875 | } else { | 836 | } else { | ||
876 | errno_save = errno; | 837 | errno_save = errno; | ||
877 | qCWarning(KWIN_DRM) << "Page flip failed:" << strerror(errno); | 838 | qCWarning(KWIN_DRM) << "Page flip failed:" << strerror(errno); | ||
878 | delete buffer; | 839 | delete buffer; | ||
879 | } | 840 | } | ||
880 | return ok; | 841 | return ok; | ||
881 | } | 842 | } | ||
882 | 843 | | |||
883 | bool DrmOutput::setModeLegacy(DrmBuffer *buffer) | 844 | bool DrmOutput::setModeLegacy(DrmBuffer *buffer) | ||
884 | { | 845 | { | ||
885 | if (drmModeSetCrtc(m_backend->fd(), m_crtcId, buffer->bufferId(), 0, 0, &m_connector, 1, &m_mode) == 0) { | 846 | uint32_t connId = m_conn->id(); | ||
847 | if (drmModeSetCrtc(m_backend->fd(), m_crtc->id(), buffer->bufferId(), 0, 0, &connId, 1, &m_mode) == 0) { | ||||
886 | m_lastStride = buffer->stride(); | 848 | m_lastStride = buffer->stride(); | ||
887 | m_lastGbm = buffer->isGbm(); | 849 | m_lastGbm = buffer->isGbm(); | ||
888 | return true; | 850 | return true; | ||
889 | } else { | 851 | } else { | ||
890 | qCWarning(KWIN_DRM) << "Mode setting failed"; | 852 | qCWarning(KWIN_DRM) << "Mode setting failed"; | ||
891 | return false; | 853 | return false; | ||
892 | } | 854 | } | ||
893 | } | 855 | } | ||
Show All 35 Lines |