D23105: WIP: [platforms/x11] Cleanup GLX backend, revise compositing

Fredrik Höglund noreply at phabricator.kde.org
Mon Aug 19 02:40:27 BST 2019


fredrik added a comment.


  In D23105#512099 <https://phabricator.kde.org/D23105#512099>, @romangg wrote:
  
  > In D23105#511957 <https://phabricator.kde.org/D23105#511957>, @fredrik wrote:
  >
  > > NVIDIA doesn't support the OML extensions. They can't be implemented efficiently on their hardware IIRC.
  > >  [...]
  >
  >
  > 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.
  
  
  That would leave the user without a way to override the driver's default vsync setting.

INLINE COMMENTS

> romangg wrote in glxbackend.cpp:718
> 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?
> 
> Related to that do you know why we `present()` in `prepareRenderingFrame` (in DRM backend as well) and not **after** the actual paint in `endRenderingFrame`?

> 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?

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.

See  `void OpenGLBackend::addToDamageHistory(const QRegion &region)` and `QRegion OpenGLBackend::accumulatedDamageHistory(int bufferAge) const`

> Related to that do you know why we present() in prepareRenderingFrame (in DRM backend as well) and not after the actual paint in endRenderingFrame?

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.

The logic can be illustrated with the following pseudo code:

  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);
  }

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.

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.

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.

But there's obviously a trade-off here between smoothness and latency.

REPOSITORY
  R108 KWin

REVISION DETAIL
  https://phabricator.kde.org/D23105

To: romangg, #kwin, fredrik
Cc: 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kwin/attachments/20190819/ec8f03ff/attachment.html>


More information about the kwin mailing list