Commit a78754b6 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii
Browse files

Fix recorded render time when glXSwapBuffers() blocks

If glXSwapBuffers() blocks, the render loop will also record how long
kwin was blocked. Obviously, we don't want that.
parent e6c1735b
......@@ -659,15 +659,10 @@ void Compositor::handleFrameRequested(RenderLoop *renderLoop)
kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PreFrame);
}
const std::chrono::milliseconds presentTime =
std::chrono::duration_cast<std::chrono::milliseconds>(renderLoop->nextPresentationTimestamp());
const QRegion repaints = m_scene->repaints(screenId);
m_scene->resetRepaints(screenId);
renderLoop->beginFrame();
m_scene->paint(screenId, repaints, windows, presentTime);
renderLoop->endFrame();
m_scene->paint(screenId, repaints, windows, renderLoop);
if (m_framesToTestForSafety > 0) {
if (m_scene->compositingType() & OpenGLCompositing) {
......
......@@ -33,6 +33,7 @@
#include "lanczosfilter.h"
#include "main.h"
#include "overlaywindow.h"
#include "renderloop.h"
#include "screens.h"
#include "cursor.h"
#include "decorations/decoratedclient.h"
......@@ -602,7 +603,7 @@ void SceneOpenGL::aboutToStartPainting(int screenId, const QRegion &damage)
}
void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Toplevel *> &toplevels,
std::chrono::milliseconds presentTime)
RenderLoop *renderLoop)
{
if (m_resetOccurred) {
return; // A graphics reset has occurred, do nothing.
......@@ -639,9 +640,10 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
} else {
int mask = 0;
updateProjectionMatrix();
renderLoop->beginFrame();
paintScreen(&mask, damage.intersected(geo), repaint, &update, &valid,
presentTime, projectionMatrix(), geo, scaling); // call generic implementation
renderLoop, projectionMatrix(), geo, scaling); // call generic implementation
paintCursor(valid);
if (!GLPlatform::instance()->isGLES() && screenId == -1) {
......@@ -659,6 +661,8 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList<Topleve
}
}
renderLoop->endFrame();
GLVertexBuffer::streamingBuffer()->endOfFrame();
m_backend->endFrame(screenId, valid, update);
GLVertexBuffer::streamingBuffer()->framePosted();
......
......@@ -36,7 +36,7 @@ public:
~SceneOpenGL() override;
bool initFailed() const override;
void paint(int screenId, const QRegion &damage, const QList<Toplevel *> &windows,
std::chrono::milliseconds presentTime) override;
RenderLoop *renderLoop) override;
Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) override;
Shadow *createShadow(Toplevel *toplevel) override;
void screenGeometryChanged(const QSize &size) override;
......
......@@ -14,6 +14,7 @@
#include "deleted.h"
#include "effects.h"
#include "main.h"
#include "renderloop.h"
#include "screens.h"
#include "toplevel.h"
#include "platform.h"
......@@ -81,7 +82,7 @@ void SceneQPainter::paintGenericScreen(int mask, const ScreenPaintData &data)
}
void SceneQPainter::paint(int screenId, const QRegion &_damage, const QList<Toplevel *> &toplevels,
std::chrono::milliseconds presentTime)
RenderLoop *renderLoop)
{
Q_ASSERT(kwinApp()->platform()->isPerScreenRenderingEnabled());
painted_screen = screenId;
......@@ -100,15 +101,17 @@ void SceneQPainter::paint(int screenId, const QRegion &_damage, const QList<Topl
const QRect geometry = screens()->geometry(screenId);
QImage *buffer = m_backend->bufferForScreen(screenId);
if (buffer && !buffer->isNull()) {
renderLoop->beginFrame();
m_painter->begin(buffer);
m_painter->setWindow(geometry);
QRegion updateRegion, validRegion;
paintScreen(&mask, damage.intersected(geometry), QRegion(), &updateRegion, &validRegion,
presentTime);
renderLoop);
paintCursor(updateRegion);
m_painter->end();
renderLoop->endFrame();
m_backend->endFrame(screenId, mask, updateRegion);
}
......
......@@ -26,7 +26,7 @@ public:
~SceneQPainter() override;
OverlayWindow* overlayWindow() const override;
void paint(int screenId, const QRegion &damage, const QList<Toplevel *> &windows,
std::chrono::milliseconds presentTime) override;
RenderLoop *renderLoop) override;
void paintGenericScreen(int mask, const ScreenPaintData &data) override;
CompositingType compositingType() const override;
bool initFailed() const override;
......
......@@ -23,6 +23,7 @@
#include "main.h"
#include "overlaywindow.h"
#include "platform.h"
#include "renderloop.h"
#include "screens.h"
#include "xcbutils.h"
#include "decorations/decoratedclient.h"
......@@ -76,7 +77,7 @@ bool SceneXrender::initFailed() const
// the entry point for painting
void SceneXrender::paint(int screenId, const QRegion &damage, const QList<Toplevel *> &toplevels,
std::chrono::milliseconds presentTime)
RenderLoop *renderLoop)
{
painted_screen = screenId;
......@@ -84,7 +85,9 @@ void SceneXrender::paint(int screenId, const QRegion &damage, const QList<Toplev
int mask = 0;
QRegion updateRegion, validRegion;
paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion, presentTime);
renderLoop->beginFrame();
paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion, renderLoop);
renderLoop->endFrame();
m_backend->showOverlay();
......
......@@ -33,7 +33,7 @@ public:
return XRenderCompositing;
}
void paint(int screenId, const QRegion &damage, const QList<Toplevel *> &windows,
std::chrono::milliseconds presentTime) override;
RenderLoop *renderLoop) override;
Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) override;
Shadow *createShadow(Toplevel *toplevel) override;
void screenGeometryChanged(const QSize &size) override;
......
......@@ -146,8 +146,7 @@ void Scene::reallocRepaints()
// returns mask and possibly modified region
void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint,
QRegion *updateRegion, QRegion *validRegion,
std::chrono::milliseconds presentTime,
QRegion *updateRegion, QRegion *validRegion, RenderLoop *renderLoop,
const QMatrix4x4 &projection, const QRect &outputGeometry,
qreal screenScale)
{
......@@ -155,6 +154,9 @@ void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint
const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height());
*mask = (damage == displayRegion) ? 0 : PAINT_SCREEN_REGION;
const std::chrono::milliseconds presentTime =
std::chrono::duration_cast<std::chrono::milliseconds>(renderLoop->nextPresentationTimestamp());
if (Q_UNLIKELY(presentTime < m_expectedPresentTimestamp)) {
qCDebug(KWIN_CORE, "Provided presentation timestamp is invalid: %ld (current: %ld)",
presentTime.count(), m_expectedPresentTimestamp.count());
......
......@@ -39,6 +39,7 @@ class Deleted;
class EffectFrameImpl;
class EffectWindowImpl;
class OverlayWindow;
class RenderLoop;
class Shadow;
class WindowPixmap;
class GLTexture;
......@@ -75,7 +76,7 @@ public:
// returns the time since the last vblank signal - if there's one
// ie. "what of this frame is lost to painting"
virtual void paint(int screenId, const QRegion &damage, const QList<Toplevel *> &windows,
std::chrono::milliseconds presentTime) = 0;
RenderLoop *renderLoop) = 0;
/**
* Adds the Toplevel to the Scene.
......@@ -208,8 +209,7 @@ protected:
void clearStackingOrder();
// shared implementation, starts painting the screen
void paintScreen(int *mask, const QRegion &damage, const QRegion &repaint,
QRegion *updateRegion, QRegion *validRegion,
std::chrono::milliseconds presentTime,
QRegion *updateRegion, QRegion *validRegion, RenderLoop *renderLoop,
const QMatrix4x4 &projection = QMatrix4x4(),
const QRect &outputGeometry = QRect(), qreal screenScale = 1.0);
// Render cursor texture in case hardware cursor is disabled/non-applicable
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment