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