Changeset View
Changeset View
Standalone View
Standalone View
plugins/platforms/drm/drm_output.cpp
Show First 20 Lines • Show All 76 Lines • ▼ Show 20 Line(s) | |||||
77 | void DrmOutput::restoreSaved() | 77 | void DrmOutput::restoreSaved() | ||
78 | { | 78 | { | ||
79 | if (!m_savedCrtc.isNull()) { | 79 | if (!m_savedCrtc.isNull()) { | ||
80 | drmModeSetCrtc(m_backend->fd(), m_savedCrtc->crtc_id, m_savedCrtc->buffer_id, | 80 | drmModeSetCrtc(m_backend->fd(), m_savedCrtc->crtc_id, m_savedCrtc->buffer_id, | ||
81 | m_savedCrtc->x, m_savedCrtc->y, &m_connector, 1, &m_savedCrtc->mode); | 81 | m_savedCrtc->x, m_savedCrtc->y, &m_connector, 1, &m_savedCrtc->mode); | ||
82 | } | 82 | } | ||
83 | } | 83 | } | ||
84 | 84 | | |||
85 | void DrmOutput::showCursor(DrmBuffer *c) | 85 | void DrmOutput::showCursor(DrmDumbBuffer *c) | ||
86 | { | 86 | { | ||
87 | const QSize &s = c->size(); | 87 | const QSize &s = c->size(); | ||
88 | drmModeSetCursor(m_backend->fd(), m_crtcId, c->handle(), s.width(), s.height()); | 88 | drmModeSetCursor(m_backend->fd(), m_crtcId, c->handle(), s.width(), s.height()); | ||
89 | } | 89 | } | ||
90 | 90 | | |||
91 | void DrmOutput::moveCursor(const QPoint &globalPos) | 91 | void DrmOutput::moveCursor(const QPoint &globalPos) | ||
92 | { | 92 | { | ||
93 | const QPoint p = globalPos - m_globalPos; | 93 | const QPoint p = globalPos - m_globalPos; | ||
▲ Show 20 Lines • Show All 565 Lines • ▼ Show 20 Line(s) | 657 | if (m_changeset->scaleChanged()) { | |||
659 | m_waylandOutputDevice->setScale(m_changeset->scale()); | 659 | m_waylandOutputDevice->setScale(m_changeset->scale()); | ||
660 | // FIXME: implement for wl_output | 660 | // FIXME: implement for wl_output | ||
661 | } | 661 | } | ||
662 | return true; | 662 | return true; | ||
663 | } | 663 | } | ||
664 | 664 | | |||
665 | void DrmOutput::pageFlipped() | 665 | void DrmOutput::pageFlipped() | ||
666 | { | 666 | { | ||
667 | // Egl based surface buffers get destroyed, QPainter based dumb buffers not | ||||
668 | // TODO1: when we later allow different buffer subclasses on planes and the front buffer, the | ||||
669 | // deleteBufferAfterPageFlip boolean needs to be replaced by individual buffer cleanup fcts | ||||
670 | // TODO2: split up DrmOutput in two for dumb and egl/gbm surface buffer compatible subclasses completely? | ||||
671 | if (m_backend->deleteBufferAfterPageFlip()) { | ||||
672 | | ||||
673 | auto bufferHandler = [] (DrmBuffer *oldbuffer, DrmBuffer *newbuffer) { | ||||
674 | if (oldbuffer != newbuffer) { | ||||
675 | delete oldbuffer; | ||||
676 | } | ||||
677 | newbuffer->releaseGbm(); | ||||
678 | }; | ||||
679 | | ||||
667 | if (m_backend->atomicModeSetting()){ | 680 | if (m_backend->atomicModeSetting()) { | ||
668 | foreach (DrmPlane *p, m_planesFlipList) { | 681 | for (DrmPlane *p : m_planesFlipList) { | ||
669 | pageFlippedBufferRemover(p->current(), p->next()); | 682 | bufferHandler(p->current(), p->next()); | ||
670 | p->setCurrent(p->next()); | 683 | p->setCurrent(p->next()); | ||
671 | p->setNext(nullptr); | 684 | p->setNext(nullptr); | ||
672 | } | 685 | } | ||
673 | m_planesFlipList.clear(); | 686 | m_planesFlipList.clear(); | ||
674 | 687 | | |||
675 | } else { | 688 | } else { | ||
676 | if (!m_nextBuffer) { | 689 | bufferHandler(m_currentBuffer, m_nextBuffer); | ||
677 | return; | | |||
678 | } | | |||
679 | pageFlippedBufferRemover(m_currentBuffer, m_nextBuffer); | | |||
680 | m_currentBuffer = m_nextBuffer; | 690 | m_currentBuffer = m_nextBuffer; | ||
681 | m_nextBuffer = nullptr; | 691 | m_nextBuffer = nullptr; | ||
682 | } | 692 | } | ||
683 | cleanupBlackBuffer(); | 693 | } else { | ||
684 | } | 694 | if (m_backend->atomicModeSetting()){ | ||
685 | 695 | for (DrmPlane *p : m_planesFlipList) { | |||
686 | void DrmOutput::pageFlippedBufferRemover(DrmBuffer *oldbuffer, DrmBuffer *newbuffer) | 696 | p->setCurrent(p->next()); | ||
687 | { | 697 | p->setNext(nullptr); | ||
688 | if (newbuffer->deleteAfterPageFlip()) { | | |||
689 | if ( oldbuffer && oldbuffer != newbuffer ) { | | |||
690 | delete oldbuffer; | | |||
691 | } | 698 | } | ||
699 | m_planesFlipList.clear(); | ||||
692 | } else { | 700 | } else { | ||
693 | // although oldbuffer's pointer is remapped in pageFlipped(), | 701 | m_currentBuffer = m_nextBuffer; | ||
694 | // we ignore the pointer completely anywhere else in this case | 702 | m_nextBuffer = nullptr; | ||
695 | newbuffer->releaseGbm(); | | |||
696 | } | 703 | } | ||
697 | } | 704 | } | ||
705 | cleanupBlackBuffer(); | ||||
706 | } | ||||
698 | 707 | | |||
699 | void DrmOutput::cleanupBlackBuffer() | 708 | void DrmOutput::cleanupBlackBuffer() | ||
700 | { | 709 | { | ||
701 | if (m_blackBuffer) { | 710 | if (m_blackBuffer) { | ||
702 | delete m_blackBuffer; | 711 | delete m_blackBuffer; | ||
703 | m_blackBuffer = nullptr; | 712 | m_blackBuffer = nullptr; | ||
704 | } | 713 | } | ||
705 | } | 714 | } | ||
Show All 21 Lines | 735 | if (m_backend->atomicModeSetting()) { | |||
727 | return presentAtomically(buffer); | 736 | return presentAtomically(buffer); | ||
728 | } else { | 737 | } else { | ||
729 | return presentLegacy(buffer); | 738 | return presentLegacy(buffer); | ||
730 | } | 739 | } | ||
731 | } | 740 | } | ||
732 | 741 | | |||
733 | bool DrmOutput::presentAtomically(DrmBuffer *buffer) | 742 | bool DrmOutput::presentAtomically(DrmBuffer *buffer) | ||
734 | { | 743 | { | ||
744 | auto bufferErrorHandler = [this] (DrmBuffer *b) { | ||||
745 | if (this->m_backend->deleteBufferAfterPageFlip()) { | ||||
746 | delete b; | ||||
747 | } else { | ||||
748 | b->releaseGbm(); | ||||
749 | } | ||||
750 | }; | ||||
751 | | ||||
735 | if (!LogindIntegration::self()->isActiveSession()) { | 752 | if (!LogindIntegration::self()->isActiveSession()) { | ||
736 | qCWarning(KWIN_DRM) << "Logind session not active."; | 753 | qCWarning(KWIN_DRM) << "Logind session not active."; | ||
737 | return false; | 754 | return false; | ||
738 | } | 755 | } | ||
739 | if (m_dpmsMode != DpmsMode::On) { | 756 | if (m_dpmsMode != DpmsMode::On) { | ||
740 | qCWarning(KWIN_DRM) << "No present() while screen off."; | 757 | qCWarning(KWIN_DRM) << "No present() while screen off."; | ||
741 | return false; | 758 | return false; | ||
742 | } | 759 | } | ||
743 | if (m_primaryPlane->next()) { | 760 | if (m_primaryPlane->next()) { | ||
744 | qCWarning(KWIN_DRM) << "Page not yet flipped."; | 761 | qCWarning(KWIN_DRM) << "Page not yet flipped."; | ||
745 | return false; | 762 | return false; | ||
746 | } | 763 | } | ||
747 | 764 | | |||
748 | DrmObject::AtomicReturn ret; | 765 | DrmObject::AtomicReturn ret; | ||
749 | uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT; | 766 | uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT; | ||
750 | 767 | | |||
751 | // TODO: throwing an exception would be really handy here! (would mean change of compile options) | 768 | // TODO: throwing an exception would be really handy here! (would mean change of compile options) | ||
752 | drmModeAtomicReq *req = drmModeAtomicAlloc(); | 769 | drmModeAtomicReq *req = drmModeAtomicAlloc(); | ||
753 | if (!req) { | 770 | if (!req) { | ||
754 | qCWarning(KWIN_DRM) << "DRM: couldn't allocate atomic request"; | 771 | qCWarning(KWIN_DRM) << "DRM: couldn't allocate atomic request"; | ||
755 | delete buffer; | 772 | bufferErrorHandler(buffer); | ||
756 | return false; | 773 | return false; | ||
757 | } | 774 | } | ||
758 | 775 | | |||
759 | // Do we need to set a new mode first? | 776 | // Do we need to set a new mode first? | ||
760 | bool doModeset = !m_primaryPlane->current(); | 777 | bool doModeset = !m_primaryPlane->current(); | ||
761 | if (doModeset) { | 778 | if (doModeset) { | ||
762 | qCDebug(KWIN_DRM) << "Atomic Modeset requested"; | 779 | qCDebug(KWIN_DRM) << "Atomic Modeset requested"; | ||
763 | 780 | | |||
764 | if (drmModeCreatePropertyBlob(m_backend->fd(), &m_mode, sizeof(m_mode), &m_blobId)) { | 781 | if (drmModeCreatePropertyBlob(m_backend->fd(), &m_mode, sizeof(m_mode), &m_blobId)) { | ||
765 | qCWarning(KWIN_DRM) << "Failed to create property blob"; | 782 | qCWarning(KWIN_DRM) << "Failed to create property blob"; | ||
766 | delete buffer; | 783 | bufferErrorHandler(buffer); | ||
767 | return false; | 784 | return false; | ||
768 | } | 785 | } | ||
769 | 786 | | |||
770 | ret = atomicReqModesetPopulate(req, true); | 787 | ret = atomicReqModesetPopulate(req, true); | ||
771 | if (ret == DrmObject::AtomicReturn::Error){ | 788 | if (ret == DrmObject::AtomicReturn::Error){ | ||
772 | drmModeAtomicFree(req); | 789 | drmModeAtomicFree(req); | ||
773 | delete buffer; | 790 | bufferErrorHandler(buffer); | ||
774 | return false; | 791 | return false; | ||
775 | } | 792 | } | ||
776 | if (ret == DrmObject::AtomicReturn::Success) { | 793 | if (ret == DrmObject::AtomicReturn::Success) { | ||
777 | flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; | 794 | flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; | ||
778 | } | 795 | } | ||
779 | } | 796 | } | ||
780 | 797 | | |||
781 | m_primaryPlane->setNext(buffer); // TODO: Later not only use the primary plane for the buffer! | 798 | m_primaryPlane->setNext(buffer); // TODO: Later not only use the primary plane for the buffer! | ||
782 | // i.e.: Assign planes | 799 | // i.e.: Assign planes | ||
783 | bool anyDamage = false; | 800 | bool anyDamage = false; | ||
784 | foreach (DrmPlane* p, m_backend->planes()){ | 801 | foreach (DrmPlane* p, m_backend->planes()){ | ||
785 | if (p->output() != this) { | 802 | if (p->output() != this) { | ||
786 | continue; | 803 | continue; | ||
787 | } | 804 | } | ||
788 | ret = p->atomicReqPlanePopulate(req); | 805 | ret = p->atomicReqPlanePopulate(req); | ||
789 | if (ret == DrmObject::AtomicReturn::Error) { | 806 | if (ret == DrmObject::AtomicReturn::Error) { | ||
790 | drmModeAtomicFree(req); | 807 | drmModeAtomicFree(req); | ||
791 | m_primaryPlane->setNext(nullptr); | 808 | m_primaryPlane->setNext(nullptr); | ||
792 | m_planesFlipList.clear(); | 809 | m_planesFlipList.clear(); | ||
793 | delete buffer; | 810 | bufferErrorHandler(buffer); | ||
794 | return false; | 811 | return false; | ||
795 | } | 812 | } | ||
796 | if (ret == DrmObject::AtomicReturn::Success) { | 813 | if (ret == DrmObject::AtomicReturn::Success) { | ||
797 | anyDamage = true; | 814 | anyDamage = true; | ||
798 | m_planesFlipList << p; | 815 | m_planesFlipList << p; | ||
799 | } | 816 | } | ||
800 | } | 817 | } | ||
801 | 818 | | |||
802 | // no damage but force flip for atleast the primary plane anyway | 819 | // no damage but force flip for atleast the primary plane anyway | ||
803 | if (!anyDamage) { | 820 | if (!anyDamage) { | ||
804 | m_primaryPlane->setPropsValid(0); | 821 | m_primaryPlane->setPropsValid(0); | ||
805 | if (m_primaryPlane->atomicReqPlanePopulate(req) == DrmObject::AtomicReturn::Error) { | 822 | if (m_primaryPlane->atomicReqPlanePopulate(req) == DrmObject::AtomicReturn::Error) { | ||
806 | drmModeAtomicFree(req); | 823 | drmModeAtomicFree(req); | ||
807 | m_primaryPlane->setNext(nullptr); | 824 | m_primaryPlane->setNext(nullptr); | ||
808 | m_planesFlipList.clear(); | 825 | m_planesFlipList.clear(); | ||
809 | delete buffer; | 826 | bufferErrorHandler(buffer); | ||
810 | return false; | 827 | return false; | ||
811 | } | 828 | } | ||
812 | m_planesFlipList << m_primaryPlane; | 829 | m_planesFlipList << m_primaryPlane; | ||
813 | } | 830 | } | ||
814 | 831 | | |||
815 | if (drmModeAtomicCommit(m_backend->fd(), req, flags, this)) { | 832 | if (drmModeAtomicCommit(m_backend->fd(), req, flags, this)) { | ||
816 | qCWarning(KWIN_DRM) << "Atomic request failed to commit:" << strerror(errno); | 833 | qCWarning(KWIN_DRM) << "Atomic request failed to commit:" << strerror(errno); | ||
817 | drmModeAtomicFree(req); | 834 | drmModeAtomicFree(req); | ||
818 | m_primaryPlane->setNext(nullptr); | 835 | m_primaryPlane->setNext(nullptr); | ||
819 | m_planesFlipList.clear(); | 836 | m_planesFlipList.clear(); | ||
820 | delete buffer; | 837 | bufferErrorHandler(buffer); | ||
821 | return false; | 838 | return false; | ||
822 | } | 839 | } | ||
823 | 840 | | |||
824 | if (doModeset) { | 841 | if (doModeset) { | ||
825 | m_crtc->setPropsValid(m_crtc->propsValid() | m_crtc->propsPending()); | 842 | m_crtc->setPropsValid(m_crtc->propsValid() | m_crtc->propsPending()); | ||
826 | m_conn->setPropsValid(m_conn->propsValid() | m_conn->propsPending()); | 843 | m_conn->setPropsValid(m_conn->propsValid() | m_conn->propsPending()); | ||
827 | } | 844 | } | ||
828 | foreach (DrmPlane* p, m_planesFlipList) { | 845 | foreach (DrmPlane* p, m_planesFlipList) { | ||
Show All 14 Lines | 859 | if (!LogindIntegration::self()->isActiveSession()) { | |||
843 | m_nextBuffer = buffer; | 860 | m_nextBuffer = buffer; | ||
844 | return false; | 861 | return false; | ||
845 | } | 862 | } | ||
846 | if (m_dpmsMode != DpmsMode::On) { | 863 | if (m_dpmsMode != DpmsMode::On) { | ||
847 | return false; | 864 | return false; | ||
848 | } | 865 | } | ||
849 | 866 | | |||
850 | // Do we need to set a new mode first? | 867 | // Do we need to set a new mode first? | ||
851 | if (m_lastStride != buffer->stride() || m_lastGbm != buffer->isGbm()){ | 868 | if (!m_currentBuffer || m_currentBuffer->modeChange(buffer)) { | ||
852 | if (!setModeLegacy(buffer)) | 869 | if (!setModeLegacy(buffer)) { | ||
853 | return false; | 870 | return false; | ||
854 | } | 871 | } | ||
872 | } | ||||
855 | int errno_save = 0; | 873 | int errno_save = 0; | ||
856 | const bool ok = drmModePageFlip(m_backend->fd(), m_crtcId, buffer->bufferId(), DRM_MODE_PAGE_FLIP_EVENT, this) == 0; | 874 | if (drmModePageFlip(m_backend->fd(), m_crtcId, buffer->bufferId(), DRM_MODE_PAGE_FLIP_EVENT, this) == 0) { | ||
857 | if (ok) { | | |||
858 | m_nextBuffer = buffer; | 875 | m_nextBuffer = buffer; | ||
876 | return true; | ||||
859 | } else { | 877 | } else { | ||
860 | errno_save = errno; | 878 | errno_save = errno; | ||
861 | qCWarning(KWIN_DRM) << "Page flip failed:" << strerror(errno); | 879 | qCWarning(KWIN_DRM) << "Page flip failed:" << strerror(errno); | ||
880 | if (m_backend->deleteBufferAfterPageFlip()) { | ||||
862 | delete buffer; | 881 | delete buffer; | ||
882 | } else { | ||||
883 | buffer->releaseGbm(); | ||||
884 | } | ||||
885 | return false; | ||||
863 | } | 886 | } | ||
864 | return ok; | | |||
865 | } | 887 | } | ||
866 | 888 | | |||
867 | bool DrmOutput::setModeLegacy(DrmBuffer *buffer) | 889 | bool DrmOutput::setModeLegacy(DrmBuffer *buffer) | ||
868 | { | 890 | { | ||
869 | if (drmModeSetCrtc(m_backend->fd(), m_crtcId, buffer->bufferId(), 0, 0, &m_connector, 1, &m_mode) == 0) { | 891 | if (drmModeSetCrtc(m_backend->fd(), m_crtcId, buffer->bufferId(), 0, 0, &m_connector, 1, &m_mode) == 0) { | ||
870 | m_lastStride = buffer->stride(); | | |||
871 | m_lastGbm = buffer->isGbm(); | | |||
872 | return true; | 892 | return true; | ||
873 | } else { | 893 | } else { | ||
874 | qCWarning(KWIN_DRM) << "Mode setting failed"; | 894 | qCWarning(KWIN_DRM) << "Mode setting failed"; | ||
875 | return false; | 895 | return false; | ||
876 | } | 896 | } | ||
877 | } | 897 | } | ||
878 | 898 | | |||
879 | DrmObject::AtomicReturn DrmOutput::atomicReqModesetPopulate(drmModeAtomicReq *req, bool enable) | 899 | DrmObject::AtomicReturn DrmOutput::atomicReqModesetPopulate(drmModeAtomicReq *req, bool enable) | ||
Show All 33 Lines |