Changeset View
Changeset View
Standalone View
Standalone View
composite.cpp
Show First 20 Lines • Show All 777 Lines • ▼ Show 20 Line(s) | 772 | { | |||
---|---|---|---|---|---|
778 | if (m_bufferSwapPending && m_composeAtSwapCompletion) | 778 | if (m_bufferSwapPending && m_composeAtSwapCompletion) | ||
779 | return; | 779 | return; | ||
780 | 780 | | |||
781 | // Don't start the timer if all outputs are disabled | 781 | // Don't start the timer if all outputs are disabled | ||
782 | if (!kwinApp()->platform()->areOutputsEnabled()) { | 782 | if (!kwinApp()->platform()->areOutputsEnabled()) { | ||
783 | return; | 783 | return; | ||
784 | } | 784 | } | ||
785 | 785 | | |||
786 | uint waitTime = 1; | 786 | uint waitTime = 1000 / refreshRate(); | ||
787 | | ||||
788 | if (m_scene->blocksForRetrace()) { | | |||
789 | | ||||
790 | // TODO: make vBlankTime dynamic?! | | |||
791 | // It's required because glXWaitVideoSync will *likely* block a full frame if one enters | | |||
792 | // a retrace pass which can last a variable amount of time, depending on the actual screen | | |||
793 | // Now, my ooold 19" CRT can do such retrace so that 2ms are entirely sufficient, | | |||
794 | // while another ooold 15" TFT requires about 6ms | | |||
795 | | ||||
796 | qint64 padding = m_timeSinceLastVBlank; | | |||
797 | if (padding > fpsInterval) { | | |||
798 | // We're at low repaints or spent more time in painting than the user wanted to wait | | |||
799 | // for that frame. Align to next vblank: | | |||
800 | padding = vBlankInterval - (padding % vBlankInterval); | | |||
801 | } else { | | |||
802 | // Align to the next maxFps tick: | | |||
803 | // "remaining time of the first vsync" + "time for the other vsyncs of the frame" | | |||
804 | padding = ((vBlankInterval - padding % vBlankInterval) + | | |||
805 | (fpsInterval / vBlankInterval - 1) * vBlankInterval); | | |||
806 | } | | |||
807 | | ||||
808 | if (padding < options->vBlankTime()) { | | |||
809 | // We'll likely miss this frame so we add one: | | |||
810 | waitTime = nanoToMilli(padding + vBlankInterval - options->vBlankTime()); | | |||
811 | } else { | | |||
812 | waitTime = nanoToMilli(padding - options->vBlankTime()); | | |||
813 | } | | |||
zzag: I think we still need some of this code. Syncing to vblank will be a problem though. | |||||
814 | } | | |||
815 | else { // w/o blocking vsync we just jump to the next demanded tick | | |||
816 | if (fpsInterval > m_timeSinceLastVBlank) { | | |||
817 | waitTime = nanoToMilli(fpsInterval - m_timeSinceLastVBlank); | | |||
818 | if (!waitTime) { | | |||
819 | // Will ensure we don't block out the eventloop - the system's just not faster ... | | |||
820 | waitTime = 1; | | |||
821 | } | | |||
822 | } | | |||
823 | /* else if (m_timeSinceLastVBlank - fpsInterval < (vBlankInterval<<1)) { | | |||
824 | // NOTICE - "for later" ------------------------------------------------------------------ | | |||
825 | // It can happen that we push two frames within one refresh cycle. | | |||
826 | // Swapping will then block even with triple buffering when the GPU does not discard but | | |||
827 | // queues frames | | |||
828 | // now here's the mean part: if we take that as "OMG, we're late - next frame ASAP", | | |||
829 | // there'll immediately be 2 frames in the pipe, swapping will block, we think we're | | |||
830 | // late ... ewww | | |||
831 | // so instead we pad to the clock again and add 2ms safety to ensure the pipe is really | | |||
832 | // free | | |||
833 | // NOTICE: obviously m_timeSinceLastVBlank can be too big because we're too slow as well | | |||
834 | // So if this code was enabled, we'd needlessly half the framerate once more (15 instead of 30) | | |||
835 | waitTime = nanoToMilli(vBlankInterval - (m_timeSinceLastVBlank - fpsInterval)%vBlankInterval) + 2; | | |||
836 | }*/ | | |||
837 | else { | | |||
838 | // "0" would be sufficient here, but the compositor isn't the WMs only task. | | |||
839 | waitTime = 1; | | |||
840 | } | | |||
841 | } | | |||
842 | // Force 4fps minimum: | 787 | // Force 4fps minimum: | ||
843 | compositeTimer.start(qMin(waitTime, 250u), this); | 788 | compositeTimer.start(qMin(waitTime, 250u), this); | ||
844 | } | 789 | } | ||
845 | 790 | | |||
846 | bool Compositor::isActive() | 791 | bool Compositor::isActive() | ||
847 | { | 792 | { | ||
848 | return m_state == State::On; | 793 | return m_state == State::On; | ||
849 | } | 794 | } | ||
Show All 12 Lines | |||||
862 | 807 | | |||
863 | void WaylandCompositor::start() | 808 | void WaylandCompositor::start() | ||
864 | { | 809 | { | ||
865 | if (!Compositor::setupStart()) { | 810 | if (!Compositor::setupStart()) { | ||
866 | // Internal setup failed, abort. | 811 | // Internal setup failed, abort. | ||
867 | return; | 812 | return; | ||
868 | } | 813 | } | ||
869 | 814 | | |||
815 | // TODO: This is problematic on Wayland. We should get the highest refresh rate | ||||
816 | // and not the one of the first output. Also on hotplug reevaluate. | ||||
817 | // On X11 do it also like this? | ||||
818 | m_refreshRate = KWin::currentRefreshRate(); | ||||
819 | | ||||
870 | if (Workspace::self()) { | 820 | if (Workspace::self()) { | ||
871 | startupWithWorkspace(); | 821 | startupWithWorkspace(); | ||
872 | } else { | 822 | } else { | ||
873 | connect(kwinApp(), &Application::workspaceCreated, | 823 | connect(kwinApp(), &Application::workspaceCreated, | ||
874 | this, &WaylandCompositor::startupWithWorkspace); | 824 | this, &WaylandCompositor::startupWithWorkspace); | ||
875 | } | 825 | } | ||
876 | } | 826 | } | ||
877 | 827 | | |||
878 | int WaylandCompositor::refreshRate() const | 828 | int WaylandCompositor::refreshRate() const | ||
879 | { | 829 | { | ||
880 | // TODO: This makes no sense on Wayland. First step would be to atleast | 830 | return m_refreshRate; | ||
881 | // set the refresh rate to the highest available one. Second step | | |||
882 | // would be to not use a uniform value at all but per screen. | | |||
883 | return KWin::currentRefreshRate(); | | |||
884 | } | 831 | } | ||
885 | 832 | | |||
886 | X11Compositor::X11Compositor(QObject *parent) | 833 | X11Compositor::X11Compositor(QObject *parent) | ||
887 | : Compositor(parent) | 834 | : Compositor(parent) | ||
888 | , m_suspended(options->isUseCompositing() ? NoReasonSuspend : UserSuspend) | 835 | , m_suspended(options->isUseCompositing() ? NoReasonSuspend : UserSuspend) | ||
889 | , m_xrrRefreshRate(0) | 836 | , m_xrrRefreshRate(0) | ||
890 | { | 837 | { | ||
891 | } | 838 | } | ||
▲ Show 20 Lines • Show All 161 Lines • Show Last 20 Lines |
I think we still need some of this code. Syncing to vblank will be a problem though.