| 141 | } |
| 142 | |
| 143 | void RenderLoopPrivate::notifyFrameCompleted(std::chrono::nanoseconds timestamp, std::optional<RenderTimeSpan> renderTime, PresentationMode mode, OutputFrame *frame) |
| 144 | { |
| 145 | if (output && s_printDebugInfo && !m_debugOutput) { |
| 146 | m_debugOutput = std::fstream(qPrintable("kwin perf statistics " + output->name() + ".csv"), std::ios::out); |
| 147 | *m_debugOutput << "target pageflip timestamp,pageflip timestamp,render start,render end,safety margin,refresh duration,vrr,tearing,predicted render time\n"; |
| 148 | } |
| 149 | if (m_debugOutput) { |
| 150 | auto times = renderTime.value_or(RenderTimeSpan{}); |
| 151 | const bool vrr = mode == PresentationMode::AdaptiveSync || mode == PresentationMode::AdaptiveAsync; |
| 152 | const bool tearing = mode == PresentationMode::Async || mode == PresentationMode::AdaptiveAsync; |
| 153 | *m_debugOutput << frame->targetPageflipTime().time_since_epoch().count() << "," << timestamp.count() << "," << times.start.time_since_epoch().count() << "," << times.end.time_since_epoch().count() |
| 154 | << "," << safetyMargin.count() << "," << frame->refreshDuration().count() << "," << (vrr ? 1 : 0) << "," << (tearing ? 1 : 0) << "," << frame->predictedRenderTime().count() << "\n"; |
| 155 | } |
| 156 | |
| 157 | Q_ASSERT(pendingFrameCount > 0); |
| 158 | pendingFrameCount--; |
| 159 | |
| 160 | notifyVblank(timestamp); |
| 161 | |
| 162 | if (renderTime) { |
| 163 | renderJournal.add(renderTime->end - renderTime->start, timestamp); |
| 164 | } |
| 165 | if (compositeTimer.isActive()) { |
| 166 | // reschedule to match the new timestamp and render time |
| 167 | scheduleRepaint(lastPresentationTimestamp); |
| 168 | } |
| 169 | if (!inhibitCount && pendingReschedule) { |
| 170 | scheduleNextRepaint(); |
| 171 | } |
| 172 | |
| 173 | Q_EMIT q->framePresented(q, timestamp, mode); |
| 174 | } |
| 175 | |
| 176 | void RenderLoopPrivate::notifyVblank(std::chrono::nanoseconds timestamp) |
| 177 | { |
no test coverage detected