Drop flag to indicate if swap buffers is blocking
We want the new compositing timing algorithm to be invariant regarding whether glXSwapBuffers() or eglSwapBuffers() block.
This commit is contained in:
parent
2152598cc4
commit
7a3fa88f02
11 changed files with 23 additions and 101 deletions
|
@ -789,60 +789,32 @@ void Compositor::setCompositeTimer()
|
|||
|
||||
uint waitTime = 1;
|
||||
|
||||
if (m_scene->blocksForRetrace()) {
|
||||
|
||||
// TODO: make vBlankTime dynamic?!
|
||||
// It's required because glXWaitVideoSync will *likely* block a full frame if one enters
|
||||
// a retrace pass which can last a variable amount of time, depending on the actual screen
|
||||
// Now, my ooold 19" CRT can do such retrace so that 2ms are entirely sufficient,
|
||||
// while another ooold 15" TFT requires about 6ms
|
||||
|
||||
qint64 padding = m_timeSinceLastVBlank;
|
||||
if (padding > fpsInterval) {
|
||||
// We're at low repaints or spent more time in painting than the user wanted to wait
|
||||
// for that frame. Align to next vblank:
|
||||
padding = vBlankInterval - (padding % vBlankInterval);
|
||||
} else {
|
||||
// Align to the next maxFps tick:
|
||||
// "remaining time of the first vsync" + "time for the other vsyncs of the frame"
|
||||
padding = ((vBlankInterval - padding % vBlankInterval) +
|
||||
(fpsInterval / vBlankInterval - 1) * vBlankInterval);
|
||||
}
|
||||
|
||||
if (padding < options->vBlankTime()) {
|
||||
// We'll likely miss this frame so we add one:
|
||||
waitTime = nanoToMilli(padding + vBlankInterval - options->vBlankTime());
|
||||
} else {
|
||||
waitTime = nanoToMilli(padding - options->vBlankTime());
|
||||
}
|
||||
}
|
||||
else { // w/o blocking vsync we just jump to the next demanded tick
|
||||
if (fpsInterval > m_timeSinceLastVBlank) {
|
||||
waitTime = nanoToMilli(fpsInterval - m_timeSinceLastVBlank);
|
||||
if (!waitTime) {
|
||||
// Will ensure we don't block out the eventloop - the system's just not faster ...
|
||||
waitTime = 1;
|
||||
}
|
||||
}
|
||||
/* else if (m_scene->syncsToVBlank() && m_timeSinceLastVBlank - fpsInterval < (vBlankInterval<<1)) {
|
||||
// NOTICE - "for later" ------------------------------------------------------------------
|
||||
// It can happen that we push two frames within one refresh cycle.
|
||||
// Swapping will then block even with triple buffering when the GPU does not discard but
|
||||
// queues frames
|
||||
// now here's the mean part: if we take that as "OMG, we're late - next frame ASAP",
|
||||
// there'll immediately be 2 frames in the pipe, swapping will block, we think we're
|
||||
// late ... ewww
|
||||
// so instead we pad to the clock again and add 2ms safety to ensure the pipe is really
|
||||
// free
|
||||
// NOTICE: obviously m_timeSinceLastVBlank can be too big because we're too slow as well
|
||||
// So if this code was enabled, we'd needlessly half the framerate once more (15 instead of 30)
|
||||
waitTime = nanoToMilli(vBlankInterval - (m_timeSinceLastVBlank - fpsInterval)%vBlankInterval) + 2;
|
||||
}*/
|
||||
else {
|
||||
// "0" would be sufficient here, but the compositor isn't the WMs only task.
|
||||
if (fpsInterval > m_timeSinceLastVBlank) {
|
||||
waitTime = nanoToMilli(fpsInterval - m_timeSinceLastVBlank);
|
||||
if (!waitTime) {
|
||||
// Will ensure we don't block out the eventloop - the system's just not faster ...
|
||||
waitTime = 1;
|
||||
}
|
||||
}
|
||||
/* else if (m_scene->syncsToVBlank() && m_timeSinceLastVBlank - fpsInterval < (vBlankInterval<<1)) {
|
||||
// NOTICE - "for later" ------------------------------------------------------------------
|
||||
// It can happen that we push two frames within one refresh cycle.
|
||||
// Swapping will then block even with triple buffering when the GPU does not discard but
|
||||
// queues frames
|
||||
// now here's the mean part: if we take that as "OMG, we're late - next frame ASAP",
|
||||
// there'll immediately be 2 frames in the pipe, swapping will block, we think we're
|
||||
// late ... ewww
|
||||
// so instead we pad to the clock again and add 2ms safety to ensure the pipe is really
|
||||
// free
|
||||
// NOTICE: obviously m_timeSinceLastVBlank can be too big because we're too slow as well
|
||||
// So if this code was enabled, we'd needlessly half the framerate once more (15 instead of 30)
|
||||
waitTime = nanoToMilli(vBlankInterval - (m_timeSinceLastVBlank - fpsInterval)%vBlankInterval) + 2;
|
||||
}*/
|
||||
else {
|
||||
// "0" would be sufficient here, but the compositor isn't the WMs only task.
|
||||
waitTime = 1;
|
||||
}
|
||||
|
||||
// Force 4fps minimum:
|
||||
compositeTimer.start(qMin(waitTime, 250u), this);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace KWin
|
|||
|
||||
OpenGLBackend::OpenGLBackend()
|
||||
: m_syncsToVBlank(false)
|
||||
, m_blocksForRetrace(false)
|
||||
, m_directRendering(false)
|
||||
, m_haveBufferAge(false)
|
||||
, m_failed(false)
|
||||
|
|
|
@ -93,15 +93,6 @@ public:
|
|||
bool syncsToVBlank() const {
|
||||
return m_syncsToVBlank;
|
||||
}
|
||||
/**
|
||||
* @brief Whether VSync blocks execution until the screen is in the retrace
|
||||
*
|
||||
* Case for waitVideoSync and non triple buffering buffer swaps
|
||||
*
|
||||
*/
|
||||
bool blocksForRetrace() const {
|
||||
return m_blocksForRetrace;
|
||||
}
|
||||
/**
|
||||
* @brief Whether the backend uses direct rendering.
|
||||
*
|
||||
|
@ -189,16 +180,6 @@ protected:
|
|||
void setSyncsToVBlank(bool enabled) {
|
||||
m_syncsToVBlank = enabled;
|
||||
}
|
||||
/**
|
||||
* @brief Sets whether the VSync iplementation blocks
|
||||
*
|
||||
* Should be called by the concrete subclass once it is determined how VSync works.
|
||||
* If the subclass does not call this method, the backend defaults to @c false.
|
||||
* @param enabled @c true if VSync blocks, @c false otherwise.
|
||||
*/
|
||||
void setBlocksForRetrace(bool enabled) {
|
||||
m_blocksForRetrace = enabled;
|
||||
}
|
||||
/**
|
||||
* @brief Sets whether the OpenGL context is direct.
|
||||
*
|
||||
|
@ -250,10 +231,6 @@ private:
|
|||
* @brief Whether VSync is available and used, defaults to @c false.
|
||||
*/
|
||||
bool m_syncsToVBlank;
|
||||
/**
|
||||
* @brief Whether present() will block execution until the next vertical retrace @c false.
|
||||
*/
|
||||
bool m_blocksForRetrace;
|
||||
/**
|
||||
* @brief Whether direct rendering is used, defaults to @c false.
|
||||
*/
|
||||
|
|
|
@ -34,17 +34,11 @@ void EglMultiBackend::init()
|
|||
for (auto b : qAsConst(m_backends)) {
|
||||
b->init();
|
||||
}
|
||||
// set all the values:
|
||||
// if any block, set it to be blocking
|
||||
setBlocksForRetrace(false);
|
||||
// if any don't support it set it to not supported
|
||||
setSupportsBufferAge(true);
|
||||
setSupportsPartialUpdate(true);
|
||||
setSupportsSwapBuffersWithDamage(true);
|
||||
for (auto b : qAsConst(m_backends)) {
|
||||
if (b->blocksForRetrace()) {
|
||||
setBlocksForRetrace(true);
|
||||
}
|
||||
if (!b->supportsBufferAge()) {
|
||||
setSupportsBufferAge(false);
|
||||
}
|
||||
|
|
|
@ -111,7 +111,6 @@ void EglOnXBackend::init()
|
|||
}
|
||||
|
||||
setSyncsToVBlank(false);
|
||||
setBlocksForRetrace(false);
|
||||
if (surfaceHasSubPost) {
|
||||
qCDebug(KWIN_CORE) << "EGL implementation and surface support eglPostSubBufferNV, let's use it";
|
||||
|
||||
|
|
|
@ -216,7 +216,6 @@ void GlxBackend::init()
|
|||
}
|
||||
|
||||
setSyncsToVBlank(false);
|
||||
setBlocksForRetrace(false);
|
||||
haveWaitSync = false;
|
||||
const bool wantSync = options->glPreferBufferSwap() != Options::NoSwapEncourage;
|
||||
if (wantSync && glXIsDirect(display(), ctx)) {
|
||||
|
@ -227,7 +226,6 @@ void GlxBackend::init()
|
|||
unsigned int sync;
|
||||
if (glXGetVideoSyncSGI(&sync) == 0 && glXWaitVideoSyncSGI(1, 0, &sync) == 0) {
|
||||
setSyncsToVBlank(true);
|
||||
setBlocksForRetrace(true);
|
||||
haveWaitSync = true;
|
||||
} else
|
||||
qCWarning(KWIN_X11STANDALONE) << "NO VSYNC! glXSwapInterval is not supported, glXWaitVideoSync is supported but broken";
|
||||
|
|
|
@ -487,11 +487,6 @@ bool SceneOpenGL::syncsToVBlank() const
|
|||
return m_backend->syncsToVBlank();
|
||||
}
|
||||
|
||||
bool SceneOpenGL::blocksForRetrace() const
|
||||
{
|
||||
return m_backend->blocksForRetrace();
|
||||
}
|
||||
|
||||
bool SceneOpenGL::initFailed() const
|
||||
{
|
||||
return !init_ok;
|
||||
|
|
|
@ -41,7 +41,6 @@ public:
|
|||
void screenGeometryChanged(const QSize &size) override;
|
||||
OverlayWindow *overlayWindow() const override;
|
||||
bool usesOverlayWindow() const override;
|
||||
bool blocksForRetrace() const override;
|
||||
bool syncsToVBlank() const override;
|
||||
bool makeOpenGLContextCurrent() override;
|
||||
void doneOpenGLContextCurrent() override;
|
||||
|
|
|
@ -615,11 +615,6 @@ void Scene::extendPaintRegion(QRegion ®ion, bool opaqueFullscreen)
|
|||
Q_UNUSED(opaqueFullscreen);
|
||||
}
|
||||
|
||||
bool Scene::blocksForRetrace() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Scene::syncsToVBlank() const
|
||||
{
|
||||
return false;
|
||||
|
|
1
scene.h
1
scene.h
|
@ -133,7 +133,6 @@ public:
|
|||
enum ImageFilterType { ImageFilterFast, ImageFilterGood };
|
||||
// there's nothing to paint (adjust time_diff later)
|
||||
void idle();
|
||||
virtual bool blocksForRetrace() const;
|
||||
virtual bool syncsToVBlank() const;
|
||||
virtual OverlayWindow* overlayWindow() const = 0;
|
||||
|
||||
|
|
|
@ -1624,11 +1624,6 @@ QString Workspace::supportInformation() const
|
|||
}
|
||||
|
||||
support.append(QStringLiteral("OpenGL 2 Shaders are used\n"));
|
||||
support.append(QStringLiteral("Painting blocks for vertical retrace: "));
|
||||
if (m_compositor->scene()->blocksForRetrace())
|
||||
support.append(QStringLiteral(" yes\n"));
|
||||
else
|
||||
support.append(QStringLiteral(" no\n"));
|
||||
break;
|
||||
}
|
||||
case XRenderCompositing:
|
||||
|
|
Loading…
Reference in a new issue