<table><tr><td style="">fredrik added a comment.
</td><a style="text-decoration: none; padding: 4px 8px; margin: 0 8px 8px; float: right; color: #464C5C; font-weight: bold; border-radius: 3px; background-color: #F7F7F9; background-image: linear-gradient(to bottom,#fff,#f1f0f1); display: inline-block; border: 1px solid rgba(71,87,120,.2);" href="https://phabricator.kde.org/D23105">View Revision</a></tr></table><br /><div><div><blockquote style="border-left: 3px solid #8C98B8;
color: #6B748C;
font-style: italic;
margin: 4px 0 12px 0;
padding: 8px 12px;
background-color: #F8F9FC;">
<div style="font-style: normal;
padding-bottom: 4px;">In <a href="https://phabricator.kde.org/D23105#512099" style="background-color: #e7e7e7;
border-color: #e7e7e7;
border-radius: 3px;
padding: 0 4px;
font-weight: bold;
color: black;text-decoration: none;">D23105#512099</a>, <a href="https://phabricator.kde.org/p/romangg/" style="
border-color: #f1f7ff;
color: #19558d;
background-color: #f1f7ff;
border: 1px solid transparent;
border-radius: 3px;
font-weight: bold;
padding: 0 4px;">@romangg</a> wrote:</div>
<div style="margin: 0;
padding: 0;
border: 0;
color: rgb(107, 116, 140);"><blockquote style="border-left: 3px solid #8C98B8;
color: #6B748C;
font-style: italic;
margin: 4px 0 12px 0;
padding: 8px 12px;
background-color: #F8F9FC;">
<div style="font-style: normal;
padding-bottom: 4px;">In <a href="https://phabricator.kde.org/D23105#511957" style="background-color: #e7e7e7;
border-color: #e7e7e7;
border-radius: 3px;
padding: 0 4px;
font-weight: bold;
color: black;text-decoration: none;">D23105#511957</a>, <a href="https://phabricator.kde.org/p/fredrik/" style="
border-color: #f1f7ff;
color: #19558d;
background-color: #f1f7ff;
border: 1px solid transparent;
border-radius: 3px;
font-weight: bold;
padding: 0 4px;">@fredrik</a> wrote:</div>
<div style="margin: 0;
padding: 0;
border: 0;
color: rgb(107, 116, 140);"><p>NVIDIA doesn't support the OML extensions. They can't be implemented efficiently on their hardware IIRC.<br />
[...]</p></div>
</blockquote>
<p>That's good to know. Thanks! I believe we can let in some of these extensions again without increasing the complexity too much as long as the SGI ones is ignored and we have no manual control of vsync. The complexity in the old code came mostly from that.</p></div>
</blockquote>
<p>That would leave the user without a way to override the driver's default vsync setting.</p></div></div><br /><div><strong>INLINE COMMENTS</strong><div><div style="margin: 6px 0 12px 0;"><div style="border: 1px solid #C7CCD9; border-radius: 3px;"><div style="padding: 0; background: #F7F7F7; border-color: #e3e4e8; border-style: solid; border-width: 0 0 1px 0; margin: 0;"><div style="color: #74777d; background: #eff2f4; padding: 6px 8px; overflow: hidden;"><a style="float: right; text-decoration: none;" href="https://phabricator.kde.org/D23105#inline-130669">View Inline</a><span style="color: #4b4d51; font-weight: bold;">romangg</span> wrote in <span style="color: #4b4d51; font-weight: bold;">glxbackend.cpp:718</span></div>
<div style="margin: 8px 0; padding: 0 12px; color: #74777D;"><p style="padding: 0; margin: 8px;">Ok and in other case the back buffer also has what's currently on the front buffer and we can paint it partly over and then swap?</p>
<p style="padding: 0; margin: 8px;">Related to that do you know why we <tt style="background: #ebebeb; font-size: 13px;">present()</tt> in <tt style="background: #ebebeb; font-size: 13px;">prepareRenderingFrame</tt> (in DRM backend as well) and not <strong>after</strong> the actual paint in <tt style="background: #ebebeb; font-size: 13px;">endRenderingFrame</tt>?</p></div></div>
<div style="margin: 8px 0; padding: 0 12px;"><blockquote style="border-left: 3px solid #a7b5bf; color: #464c5c; font-style: italic; margin: 4px 0 12px 0; padding: 4px 12px; background-color: #f8f9fc;"><p style="padding: 0; margin: 8px;">Ok and in other case the back buffer also has what's currently on the front buffer and we can paint it partly over and then swap?</p></blockquote>
<p style="padding: 0; margin: 8px;">No, but the buffer age extension makes it possible to query the number of frames that have elapsed since the current back buffer was the front buffer. Based on that we can calculate how much we need to repaint to bring it up-to-date.</p>
<p style="padding: 0; margin: 8px;">See <tt style="background: #ebebeb; font-size: 13px;">void OpenGLBackend::addToDamageHistory(const QRegion ®ion)</tt> and <tt style="background: #ebebeb; font-size: 13px;">QRegion OpenGLBackend::accumulatedDamageHistory(int bufferAge) const</tt></p>
<blockquote style="border-left: 3px solid #a7b5bf; color: #464c5c; font-style: italic; margin: 4px 0 12px 0; padding: 4px 12px; background-color: #f8f9fc;"><p style="padding: 0; margin: 8px;">Related to that do you know why we present() in prepareRenderingFrame (in DRM backend as well) and not after the actual paint in endRenderingFrame?</p></blockquote>
<p style="padding: 0; margin: 8px;">This code was written based on the idea that SwapBuffers() blocks until the swap is complete, which also means that it blocks until the next vblank.</p>
<p style="padding: 0; margin: 8px;">The logic can be illustrated with the following pseudo code:</p>
<div class="remarkup-code-block" style="margin: 12px 0;" data-code-lang="text" data-sigil="remarkup-code-block"><pre class="remarkup-code" style="font: 11px/15px "Menlo", "Consolas", "Monaco", monospace; padding: 12px; margin: 0; background: rgba(71, 87, 120, 0.08);">while (true) {
SwapBuffers(); // For the previous frame
renderTimer.start();
paint();
glFlush();
// Sleep until just before the next vblank
int timeSinceLastVBlank = renderTimer.elapsed();
sleep(vblankInterval - timeSinceLastVBlank);
}</pre></div>
<p style="padding: 0; margin: 8px;">In practice we don't call sleep of course; instead we start the composite timer with the timeout set to just before the next vblank, and return to the event loop.</p>
<p style="padding: 0; margin: 8px;">But the only driver where SwapBuffers() behaves like this is the NVIDIA driver, and its not the default behavior. It's enabled by setting __GL_MaxFramesAllowed to 1 before initializing OpenGL.</p>
<p style="padding: 0; margin: 8px;">The reason the next frame is rendered immediately after the buffer swap instead of doing it as late as possible is to avoid missing the vblank when there is a sudden increase in render time. Also if we miss the vblank by one millisecond, the main thread will be blocked in SwapBuffers for 15 milliseconds, which is less than ideal.</p>
<p style="padding: 0; margin: 8px;">But there's obviously a trade-off here between smoothness and latency.</p></div></div></div></div></div><br /><div><strong>REPOSITORY</strong><div><div>R108 KWin</div></div></div><br /><div><strong>REVISION DETAIL</strong><div><a href="https://phabricator.kde.org/D23105">https://phabricator.kde.org/D23105</a></div></div><br /><div><strong>To: </strong>romangg, KWin, fredrik<br /><strong>Cc: </strong>nicolasfella, alexeymin, kwin, LeGast00n, The-Feren-OS-Dev, sbergeron, jraleigh, fbampaloukas, GB_2, mkulinski, ragreen, jackyalcine, Pitel, iodelay, crozbo, bwowk, ZrenBot, ngraham, himcesjf, lesliezhai, ali-mohamed, hardening, romangg, jensreuterberg, abetts, sebas, apol, mart<br /></div>