Merge branch 'KDE/4.11' into master

Conflicts:
	CMakeLists.txt
	doc/kcontrol/screensaver/index.docbook
	kcontrol/krdb/krdb.cpp
	kscreensaver/kblank_screensaver/kblank.desktop
	kscreensaver/krandom_screensaver/krandom.desktop
	kscreensaver/libkscreensaver/main.cpp
	ksplash/ksplashqml/SplashApp.cpp
	kstyles/oxygen/config/main.cpp
	kstyles/oxygen/demo/main.cpp
	kstyles/oxygen/oxygenstylehelper.cpp
	kwin/clients/oxygen/config/oxygenexceptiondialog.cpp
	kwin/clients/oxygen/config/ui/oxygenconfigurationui.ui
	kwin/clients/oxygen/config/ui/oxygenexceptiondialog.ui
	kwin/clients/oxygen/demo/main.cpp
	kwin/clients/oxygen/oxygenconfigdata.kcfg
	kwin/egl_wayland_backend.cpp
	kwin/eglonxbackend.h
	kwin/glxbackend.cpp
	kwin/glxbackend.h
	kwin/kcmkwin/kwinoptions/kwinactions.desktop
	kwin/scene_opengl.cpp
	kwin/scene_opengl.h
	plasma/desktop/applets/pager/pager.cpp
	plasma/desktop/shell/activitymanager/activitymanager.cpp
	plasma/desktop/shell/activitymanager/activitymanager.h
	plasma/desktop/shell/controllerwindow.cpp
	plasma/desktop/shell/data/plasma-desktop.desktop
	plasma/generic/dataengines/geolocation/geolocation.cpp
	plasma/generic/dataengines/nowplaying/plasma-dataengine-nowplaying.desktop
	plasma/generic/wallpapers/color/plasma-wallpaper-color.desktop
	plasma/generic/wallpapers/image/image.cpp
	plasma/generic/wallpapers/image/image.h
This commit is contained in:
Martin Gräßlin 2014-01-07 09:28:59 +01:00
commit afbc5222e1
12 changed files with 281 additions and 45 deletions

View file

@ -172,7 +172,7 @@ Comment[zh_TW]=下一代桌面的樣式
X-KDE-Library=kwin3_oxygen
X-KDE-PluginInfo-Author=Nuno Pinheiro, Casper Boemann, Riccardo Iaconelli, Huynh Huu Long, Thomas Luebking, Hugo Pereira Da Costa, Matthew Woehlke
X-KDE-PluginInfo-Email=nuno@oxygen-icons.org, cbr@boemann.dk, riccardo@kde.org, long.upcase@googlemail.com, thomas.luebking@web.de, hugo@oxygen-icons.org, mw_triad@users.sourceforge.net
X-KDE-PluginInfo-Email=nuno@oxygen-icons.org, cbr@boemann.dk, riccardo@kde.org, long.upcase@googlemail.com, thomas.luebking@web.de, hugo.pereira@free.fr, mw_triad@users.sourceforge.net
X-KDE-PluginInfo-Name=Oxygen
X-KDE-PluginInfo-Category=
X-KDE-PluginInfo-Depends=

View file

@ -264,8 +264,8 @@ public:
virtual ~EglWaylandBackend();
virtual void screenGeometryChanged(const QSize &size);
virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture);
virtual void prepareRenderingFrame();
virtual void endRenderingFrame(const QRegion &damage);
virtual QRegion prepareRenderingFrame();
virtual void endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion);
Shm *shm();
protected:

View file

@ -37,6 +37,7 @@ EglOnXBackend::EglOnXBackend()
: OpenGLBackend()
, ctx(EGL_NO_CONTEXT)
, surfaceHasSubPost(0)
, m_bufferAge(0)
{
init();
// Egl is always direct rendering
@ -99,6 +100,16 @@ void EglOnXBackend::init()
}
}
}
setSupportsBufferAge(false);
if (hasGLExtension("EGL_EXT_buffer_age")) {
const QByteArray useBufferAge = qgetenv("KWIN_USE_BUFFER_AGE");
if (useBufferAge != "0")
setSupportsBufferAge(true);
}
setSyncsToVBlank(false);
setBlocksForRetrace(false);
gs_tripleBufferNeedsDetection = false;
@ -268,6 +279,13 @@ void EglOnXBackend::present()
if (lastDamage().isEmpty())
return;
if (supportsBufferAge()) {
eglSwapBuffers(dpy, surface);
eglQuerySurface(dpy, surface, EGL_BUFFER_AGE_EXT, &m_bufferAge);
setLastDamage(QRegion());
return;
}
const QRegion displayRegion(0, 0, displayWidth(), displayHeight());
const bool fullRepaint = (lastDamage() == displayRegion);
@ -312,8 +330,11 @@ void EglOnXBackend::present()
void EglOnXBackend::screenGeometryChanged(const QSize &size)
{
Q_UNUSED(size)
// no backend specific code needed
// TODO: base implementation in OpenGLBackend
// The back buffer contents are now undefined
m_bufferAge = 0;
}
SceneOpenGL::TexturePrivate *EglOnXBackend::createBackendTexture(SceneOpenGL::Texture *texture)
@ -321,8 +342,10 @@ SceneOpenGL::TexturePrivate *EglOnXBackend::createBackendTexture(SceneOpenGL::Te
return new EglTexture(texture, this);
}
void EglOnXBackend::prepareRenderingFrame()
QRegion EglOnXBackend::prepareRenderingFrame()
{
QRegion repaint;
if (gs_tripleBufferNeedsDetection) {
// the composite timer floors the repaint frequency. This can pollute our triple buffering
// detection because the glXSwapBuffers call for the new frame has to wait until the pending
@ -331,21 +354,55 @@ void EglOnXBackend::prepareRenderingFrame()
// fllush the buffer queue
usleep(1000);
}
present();
if (supportsBufferAge())
repaint = accumulatedDamageHistory(m_bufferAge);
startRenderTimer();
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
return repaint;
}
void EglOnXBackend::endRenderingFrame(const QRegion &damage)
void EglOnXBackend::endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
{
setLastDamage(damage);
glFlush();
if (damagedRegion.isEmpty()) {
setLastDamage(QRegion());
// If the damaged region of a window is fully occluded, the only
// rendering done, if any, will have been to repair a reused back
// buffer, making it identical to the front buffer.
//
// In this case we won't post the back buffer. Instead we'll just
// set the buffer age to 1, so the repaired regions won't be
// rendered again in the next frame.
if (!renderedRegion.isEmpty())
glFlush();
m_bufferAge = 1;
return;
}
setLastDamage(renderedRegion);
if (!blocksForRetrace()) {
present(); // this sets lastDamage emtpy and prevents execution from prepareRenderingFrame()
// This also sets lastDamage to empty which prevents the frame from
// being posted again when prepareRenderingFrame() is called.
present();
} else {
// Make sure that the GPU begins processing the command stream
// now and not the next time prepareRenderingFrame() is called.
glFlush();
}
if (overlayWindow()->window()) // show the window only after the first pass,
overlayWindow()->show(); // since that pass may take long
// Save the damaged region to history
if (supportsBufferAge())
addToDamageHistory(damagedRegion);
}
bool EglOnXBackend::makeCurrent()

View file

@ -34,8 +34,8 @@ public:
virtual ~EglOnXBackend();
virtual void screenGeometryChanged(const QSize &size);
virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture);
virtual void prepareRenderingFrame();
virtual void endRenderingFrame(const QRegion &damage);
virtual QRegion prepareRenderingFrame();
virtual void endRenderingFrame(const QRegion &damage, const QRegion &damagedRegion);
virtual bool makeCurrent() override;
virtual void doneCurrent() override;
@ -51,6 +51,7 @@ private:
EGLSurface surface;
EGLContext ctx;
int surfaceHasSubPost;
int m_bufferAge;
friend class EglTexture;
};

View file

@ -46,6 +46,7 @@ GlxBackend::GlxBackend()
, fbconfig(NULL)
, glxWindow(None)
, ctx(nullptr)
, m_bufferAge(0)
, haveSwapInterval(false)
{
init();
@ -104,8 +105,19 @@ void GlxBackend::init()
options->setGlPreferBufferSwap('e'); // for unknown drivers - should not happen
glPlatform->printResults();
initGL(GlxPlatformInterface);
// Check whether certain features are supported
haveSwapInterval = glXSwapIntervalMESA || glXSwapIntervalEXT || glXSwapIntervalSGI;
setSupportsBufferAge(false);
if (hasGLExtension("GLX_EXT_buffer_age")) {
const QByteArray useBufferAge = qgetenv("KWIN_USE_BUFFER_AGE");
if (useBufferAge != "0")
setSupportsBufferAge(true);
}
setSyncsToVBlank(false);
setBlocksForRetrace(false);
haveWaitSync = false;
@ -426,6 +438,13 @@ void GlxBackend::present()
if (lastDamage().isEmpty())
return;
if (supportsBufferAge()) {
glXSwapBuffers(display(), glxWindow);
glXQueryDrawable(display(), glxWindow, GLX_BACK_BUFFER_AGE_EXT, (GLuint *) &m_bufferAge);
setLastDamage(QRegion());
return;
}
const QRegion displayRegion(0, 0, displayWidth(), displayHeight());
const bool fullRepaint = (lastDamage() == displayRegion);
@ -486,6 +505,9 @@ void GlxBackend::screenGeometryChanged(const QSize &size)
makeCurrent();
glViewport(0, 0, size.width(), size.height());
// The back buffer contents are now undefined
m_bufferAge = 0;
}
SceneOpenGL::TexturePrivate *GlxBackend::createBackendTexture(SceneOpenGL::Texture *texture)
@ -493,8 +515,10 @@ SceneOpenGL::TexturePrivate *GlxBackend::createBackendTexture(SceneOpenGL::Textu
return new GlxTexture(texture, this);
}
void GlxBackend::prepareRenderingFrame()
QRegion GlxBackend::prepareRenderingFrame()
{
QRegion repaint;
if (gs_tripleBufferNeedsDetection) {
// the composite timer floors the repaint frequency. This can pollute our triple buffering
// detection because the glXSwapBuffers call for the new frame has to wait until the pending
@ -503,21 +527,55 @@ void GlxBackend::prepareRenderingFrame()
// fllush the buffer queue
usleep(1000);
}
present();
if (supportsBufferAge())
repaint = accumulatedDamageHistory(m_bufferAge);
startRenderTimer();
glXWaitX();
return repaint;
}
void GlxBackend::endRenderingFrame(const QRegion &damage)
void GlxBackend::endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
{
setLastDamage(damage);
glFlush();
if (damagedRegion.isEmpty()) {
setLastDamage(QRegion());
// If the damaged region of a window is fully occluded, the only
// rendering done, if any, will have been to repair a reused back
// buffer, making it identical to the front buffer.
//
// In this case we won't post the back buffer. Instead we'll just
// set the buffer age to 1, so the repaired regions won't be
// rendered again in the next frame.
if (!renderedRegion.isEmpty())
glFlush();
m_bufferAge = 1;
return;
}
setLastDamage(renderedRegion);
if (!blocksForRetrace()) {
present(); // this sets lastDamage emtpy and prevents execution from prepareRenderingFrame()
// This also sets lastDamage to empty which prevents the frame from
// being posted again when prepareRenderingFrame() is called.
present();
} else {
// Make sure that the GPU begins processing the command stream
// now and not the next time prepareRenderingFrame() is called.
glFlush();
}
if (overlayWindow()->window()) // show the window only after the first pass,
overlayWindow()->show(); // since that pass may take long
// Save the damaged region to history
if (supportsBufferAge())
addToDamageHistory(damagedRegion);
}
bool GlxBackend::makeCurrent()

View file

@ -44,8 +44,8 @@ public:
virtual ~GlxBackend();
virtual void screenGeometryChanged(const QSize &size);
virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture);
virtual void prepareRenderingFrame();
virtual void endRenderingFrame(const QRegion &damage);
virtual QRegion prepareRenderingFrame();
virtual void endRenderingFrame(const QRegion &damage, const QRegion &damagedRegion);
virtual bool makeCurrent() override;
virtual void doneCurrent() override;
@ -66,6 +66,7 @@ private:
GLXFBConfig fbconfig;
GLXWindow glxWindow;
GLXContext ctx;
int m_bufferAge;
bool haveSwapInterval, haveWaitSync;
friend class GlxTexture;
};

View file

@ -75,6 +75,9 @@ void KWINGLUTILS_EXPORT glResolveFunctions(OpenGLPlatformInterface platformInter
#define GL_READ_FRAMEBUFFER 0x8CA8
#endif
#ifndef GLX_BACK_BUFFER_AGE_EXT
#define GLX_BACK_BUFFER_AGE_EXT 0x20F4
#endif
#include <fixx11h.h>
@ -501,6 +504,10 @@ extern KWINGLUTILS_EXPORT glCopyBufferSubData_func glCopyBufferSubData;
#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE
#endif
#ifndef EGL_BUFFER_AGE_EXT
#define EGL_BUFFER_AGE_EXT 0x313D
#endif
#ifndef GL_UNPACK_ROW_LENGTH
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#endif

View file

@ -101,48 +101,62 @@ Scene::~Scene()
}
// returns mask and possibly modified region
void Scene::paintScreen(int* mask, QRegion* region)
void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint,
QRegion *updateRegion, QRegion *validRegion)
{
const QRegion displayRegion(0, 0, displayWidth(), displayHeight());
*mask = (*region == displayRegion) ? 0 : PAINT_SCREEN_REGION;
*mask = (damage == displayRegion) ? 0 : PAINT_SCREEN_REGION;
updateTimeDiff();
// preparation step
static_cast<EffectsHandlerImpl*>(effects)->startPaint();
QRegion region = damage;
ScreenPrePaintData pdata;
pdata.mask = *mask;
pdata.paint = *region;
pdata.paint = region;
effects->prePaintScreen(pdata, time_diff);
*mask = pdata.mask;
*region = pdata.paint;
region = pdata.paint;
if (*mask & (PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS)) {
// Region painting is not possible with transformations,
// because screen damage doesn't match transformed positions.
*mask &= ~PAINT_SCREEN_REGION;
*region = infiniteRegion();
region = infiniteRegion();
} else if (*mask & PAINT_SCREEN_REGION) {
// make sure not to go outside visible screen
*region &= displayRegion;
region &= displayRegion;
} else {
// whole screen, not transformed, force region to be full
*region = displayRegion;
region = displayRegion;
}
painted_region = *region;
painted_region = region;
repaint_region = repaint;
if (*mask & PAINT_SCREEN_BACKGROUND_FIRST) {
paintBackground(*region);
paintBackground(region);
}
ScreenPaintData data;
effects->paintScreen(*mask, *region, data);
foreach (Window * w, stacking_order) {
effects->paintScreen(*mask, region, data);
foreach (Window *w, stacking_order) {
effects->postPaintWindow(effectWindow(w));
}
effects->postPaintScreen();
*region |= painted_region;
// make sure not to go outside of the screen area
*region &= displayRegion;
*updateRegion = damaged_region;
*validRegion = (region | painted_region) & displayRegion;
repaint_region = QRegion();
damaged_region = QRegion();
// make sure all clipping is restored
Q_ASSERT(!PaintClipper::clip());
}
@ -222,6 +236,8 @@ void Scene::paintGenericScreen(int orig_mask, ScreenPaintData)
foreach (const Phase2Data & d, phase2) {
paintWindow(d.window, d.mask, d.region, d.quads);
}
damaged_region = QRegion(0, 0, displayWidth(), displayHeight());
}
// The optimized case without any transformations at all.
@ -298,8 +314,13 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
w->suspendUnredirect(data.mask & PAINT_WINDOW_TRANSLUCENT);
}
const QRegion displayRegion(0, 0, displayWidth(), displayHeight());
// Save the part of the repaint region that's exclusively rendered to
// bring a reused back buffer up to date. Then union the dirty region
// with the repaint region.
const QRegion repaintClip = repaint_region - dirtyArea;
dirtyArea |= repaint_region;
const QRegion displayRegion(0, 0, displayWidth(), displayHeight());
bool fullRepaint(dirtyArea == displayRegion); // spare some expensive region operations
if (!fullRepaint) {
extendPaintRegion(dirtyArea, opaqueFullscreen);
@ -307,6 +328,8 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
}
QRegion allclips, upperTranslucentDamage;
upperTranslucentDamage = repaint_region;
// This is the occlusion culling pass
for (int i = phase2data.count() - 1; i >= 0; --i) {
QPair< Window*, Phase2Data > *entry = &phase2data[i];
@ -351,10 +374,21 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
paintWindow(data->window, data->mask, data->region, data->quads);
}
if (fullRepaint)
if (fullRepaint) {
painted_region = displayRegion;
else
damaged_region = displayRegion;
} else {
painted_region |= paintedArea;
// Clip the repainted region from the damaged region.
// It's important that we don't add the union of the damaged region
// and the repainted region to the damage history. Otherwise the
// repaint region will grow with every frame until it eventually
// covers the whole back buffer, at which point we're always doing
// full repaints.
damaged_region = paintedArea - repaintClip;
}
}
static Scene::Window *s_recursionCheck = NULL;

View file

@ -117,7 +117,8 @@ public Q_SLOTS:
virtual void windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted) = 0;
protected:
// shared implementation, starts painting the screen
void paintScreen(int* mask, QRegion* region);
void paintScreen(int *mask, const QRegion &damage, const QRegion &repaint,
QRegion *updateRegion, QRegion *validRegion);
friend class EffectsHandlerImpl;
// called after all effects had their paintScreen() called
void finalPaintScreen(int mask, QRegion region, ScreenPaintData& data);
@ -162,6 +163,10 @@ protected:
// up all the way from paintSimpleScreen() up to paintScreen(), so save them here rather
// than propagate them up in arguments.
QRegion painted_region;
// Additional damage that needs to be repaired to bring a reused back buffer up to date
QRegion repaint_region;
// The dirty region before it was unioned with repaint_region
QRegion damaged_region;
// time since last repaint
int time_diff;
QElapsedTimer last_time;

View file

@ -83,6 +83,7 @@ OpenGLBackend::OpenGLBackend()
, m_syncsToVBlank(false)
, m_blocksForRetrace(false)
, m_directRendering(false)
, m_haveBufferAge(false)
, m_failed(false)
{
}
@ -109,6 +110,29 @@ void OpenGLBackend::idle()
}
}
void OpenGLBackend::addToDamageHistory(const QRegion &region)
{
if (m_damageHistory.count() > 10)
m_damageHistory.removeLast();
m_damageHistory.prepend(region);
}
QRegion OpenGLBackend::accumulatedDamageHistory(int bufferAge) const
{
QRegion region;
// Note: An age of zero means the buffer contents are undefined
if (bufferAge > 0 && bufferAge <= m_damageHistory.count()) {
for (int i = 0; i < bufferAge - 1; i++)
region |= m_damageHistory[i];
} else {
region = QRegion(0, 0, displayWidth(), displayHeight());
}
return region;
}
/************************************************
* SceneOpenGL
***********************************************/
@ -343,7 +367,7 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
}
m_backend->makeCurrent();
m_backend->prepareRenderingFrame();
QRegion repaint = m_backend->prepareRenderingFrame();
const GLenum status = glGetGraphicsResetStatus();
if (status != GL_NO_ERROR) {
@ -356,22 +380,33 @@ qint64 SceneOpenGL::paint(QRegion damage, ToplevelList toplevels)
checkGLError("Paint1");
#endif
paintScreen(&mask, &damage); // call generic implementation
// After this call, updateRegion will contain the damaged region in the
// back buffer. This is the region that needs to be posted to repair
// the front buffer. It doesn't include the additional damage returned
// by prepareRenderingFrame(). validRegion is the region that has been
// repainted, and may be larger than updateRegion.
QRegion updateRegion, validRegion;
paintScreen(&mask, damage, repaint, &updateRegion, &validRegion); // call generic implementation
#ifndef KWIN_HAVE_OPENGLES
const QRegion displayRegion(0, 0, displayWidth(), displayHeight());
// copy dirty parts from front to backbuffer
if (options->glPreferBufferSwap() == Options::CopyFrontBuffer && damage != displayRegion) {
if (!m_backend->supportsBufferAge() &&
options->glPreferBufferSwap() == Options::CopyFrontBuffer &&
validRegion != displayRegion) {
glReadBuffer(GL_FRONT);
copyPixels(displayRegion - damage);
copyPixels(displayRegion - validRegion);
glReadBuffer(GL_BACK);
damage = displayRegion;
}
#endif
#ifdef CHECK_GL_ERROR
checkGLError("Paint2");
#endif
m_backend->endRenderingFrame(damage);
m_backend->endRenderingFrame(validRegion, updateRegion);
// do cleanup
stacking_order.clear();
@ -427,6 +462,9 @@ void SceneOpenGL::paintBackground(QRegion region)
void SceneOpenGL::extendPaintRegion(QRegion &region, bool opaqueFullscreen)
{
if (m_backend->supportsBufferAge())
return;
if (options->glPreferBufferSwap() == Options::ExtendDamage) { // only Extend "large" repaints
const QRegion displayRegion(0, 0, displayWidth(), displayHeight());
uint damagedPixels = 0;

View file

@ -463,23 +463,29 @@ public:
}
virtual void screenGeometryChanged(const QSize &size) = 0;
virtual SceneOpenGL::TexturePrivate *createBackendTexture(SceneOpenGL::Texture *texture) = 0;
/**
* @brief Backend specific code to prepare the rendering of a frame including flushing the
* previously rendered frame to the screen if the backend works this way.
*
* @return A region that if not empty will be repainted in addition to the damaged region
**/
virtual void prepareRenderingFrame() = 0;
virtual QRegion prepareRenderingFrame() = 0;
/**
* @brief Backend specific code to handle the end of rendering a frame.
*
* @param damage The actual updated region in this frame
* @param renderedRegion The possibly larger region that has been rendered
* @param damagedRegion The damaged region that should be posted
**/
virtual void endRenderingFrame(const QRegion &damage) = 0;
virtual void endRenderingFrame(const QRegion &damage, const QRegion &damagedRegion) = 0;
virtual bool makeCurrent() = 0;
virtual void doneCurrent() = 0;
/**
* @brief Compositor is going into idle mode, flushes any pending paints.
**/
void idle();
/**
* @return bool Whether the scene needs to flush a frame.
**/
@ -540,6 +546,21 @@ public:
bool isDirectRendering() const {
return m_directRendering;
}
bool supportsBufferAge() const {
return m_haveBufferAge;
}
/**
* Returns the damage that has accumulated since a buffer of the given age was presented.
*/
QRegion accumulatedDamageHistory(int bufferAge) const;
/**
* Saves the given region to damage history.
*/
void addToDamageHistory(const QRegion &region);
protected:
/**
* @brief Backend specific flushing of frame to screen.
@ -586,6 +607,11 @@ protected:
void setIsDirectRendering(bool direct) {
m_directRendering = direct;
}
void setSupportsBufferAge(bool value) {
m_haveBufferAge = value;
}
/**
* @return const QRegion& Damage of previously rendered frame
**/
@ -623,6 +649,10 @@ private:
* @brief Whether direct rendering is used, defaults to @c false.
**/
bool m_directRendering;
/**
* @brief Whether the backend supports GLX_EXT_buffer_age / EGL_EXT_buffer_age.
*/
bool m_haveBufferAge;
/**
* @brief Whether the initialization failed, of course default to @c false.
**/
@ -631,6 +661,10 @@ private:
* @brief Damaged region of previously rendered frame.
**/
QRegion m_lastDamage;
/**
* @brief The damage history for the past 10 frames.
*/
QList<QRegion> m_damageHistory;
/**
* @brief Timer to measure how long a frame renders.
**/

View file

@ -191,12 +191,13 @@ qint64 SceneXrender::paint(QRegion damage, ToplevelList toplevels)
}
int mask = 0;
paintScreen(&mask, &damage);
QRegion updateRegion, validRegion;
paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion);
if (m_overlayWindow->window()) // show the window only after the first pass, since
m_overlayWindow->show(); // that pass may take long
present(mask, damage);
present(mask, updateRegion);
// do cleanup
stacking_order.clear();