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