Clip software cursors
If you play some video and the software cursor doesn't hover it, then the shadow cast by the cursor will be getting darker and darker with every frame. The main reason for that is that kwin paints the software cursor even if the rect behind it hasn't been damaged or repainted.
This commit is contained in:
parent
4b12afced9
commit
4a0128cac1
8 changed files with 30 additions and 18 deletions
|
@ -197,6 +197,7 @@ void Platform::setSoftWareCursor(bool set)
|
||||||
disconnect(Cursors::self(), &Cursors::positionChanged, this, &Platform::triggerCursorRepaint);
|
disconnect(Cursors::self(), &Cursors::positionChanged, this, &Platform::triggerCursorRepaint);
|
||||||
disconnect(Cursors::self(), &Cursors::currentCursorChanged, this, &Platform::triggerCursorRepaint);
|
disconnect(Cursors::self(), &Cursors::currentCursorChanged, this, &Platform::triggerCursorRepaint);
|
||||||
}
|
}
|
||||||
|
triggerCursorRepaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Platform::triggerCursorRepaint()
|
void Platform::triggerCursorRepaint()
|
||||||
|
|
|
@ -555,7 +555,7 @@ void SceneOpenGL::insertWait()
|
||||||
* Render cursor texture in case hardware cursor is disabled.
|
* Render cursor texture in case hardware cursor is disabled.
|
||||||
* Useful for screen recording apps or backends that can't do planes.
|
* Useful for screen recording apps or backends that can't do planes.
|
||||||
*/
|
*/
|
||||||
void SceneOpenGL2::paintCursor()
|
void SceneOpenGL2::paintCursor(const QRegion &rendered)
|
||||||
{
|
{
|
||||||
Cursor* cursor = Cursors::self()->currentCursor();
|
Cursor* cursor = Cursors::self()->currentCursor();
|
||||||
|
|
||||||
|
@ -566,6 +566,18 @@ void SceneOpenGL2::paintCursor()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// figure out which part of the cursor needs to be repainted
|
||||||
|
const QPoint cursorPos = cursor->pos() - cursor->hotspot();
|
||||||
|
const qreal scale = cursor->image().devicePixelRatio();
|
||||||
|
const QRect cursorRect(QPoint(0, 0), cursor->image().size() / scale);
|
||||||
|
QRegion region;
|
||||||
|
for (const QRect &rect : rendered) {
|
||||||
|
region |= rect.translated(-cursorPos).intersected(cursorRect);
|
||||||
|
}
|
||||||
|
if (region.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// lazy init texture cursor only in case we need software rendering
|
// lazy init texture cursor only in case we need software rendering
|
||||||
if (!m_cursorTexture) {
|
if (!m_cursorTexture) {
|
||||||
auto updateCursorTexture = [this] {
|
auto updateCursorTexture = [this] {
|
||||||
|
@ -585,9 +597,6 @@ void SceneOpenGL2::paintCursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
// get cursor position in projection coordinates
|
// get cursor position in projection coordinates
|
||||||
const qreal scale = cursor->image().devicePixelRatio();
|
|
||||||
const QPoint cursorPos = cursor->pos() - cursor->hotspot();
|
|
||||||
const QRect cursorRect(QPoint(0, 0), m_cursorTexture->size() / scale);
|
|
||||||
QMatrix4x4 mvp = m_projectionMatrix;
|
QMatrix4x4 mvp = m_projectionMatrix;
|
||||||
mvp.translate(cursorPos.x(), cursorPos.y());
|
mvp.translate(cursorPos.x(), cursorPos.y());
|
||||||
|
|
||||||
|
@ -599,7 +608,7 @@ void SceneOpenGL2::paintCursor()
|
||||||
m_cursorTexture->bind();
|
m_cursorTexture->bind();
|
||||||
ShaderBinder binder(ShaderTrait::MapTexture);
|
ShaderBinder binder(ShaderTrait::MapTexture);
|
||||||
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
|
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
|
||||||
m_cursorTexture->render(QRegion(cursorRect), cursorRect);
|
m_cursorTexture->render(region, cursorRect);
|
||||||
m_cursorTexture->unbind();
|
m_cursorTexture->unbind();
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
@ -645,7 +654,7 @@ qint64 SceneOpenGL::paint(const QRegion &damage, const QList<Toplevel *> &toplev
|
||||||
updateProjectionMatrix();
|
updateProjectionMatrix();
|
||||||
|
|
||||||
paintScreen(&mask, damage.intersected(geo), repaint, &update, &valid, projectionMatrix(), geo, scaling); // call generic implementation
|
paintScreen(&mask, damage.intersected(geo), repaint, &update, &valid, projectionMatrix(), geo, scaling); // call generic implementation
|
||||||
paintCursor();
|
paintCursor(valid);
|
||||||
|
|
||||||
GLVertexBuffer::streamingBuffer()->endOfFrame();
|
GLVertexBuffer::streamingBuffer()->endOfFrame();
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ protected:
|
||||||
Scene::Window *createWindow(Toplevel *t) override;
|
Scene::Window *createWindow(Toplevel *t) override;
|
||||||
void finalDrawWindow(EffectWindowImpl* w, int mask, const QRegion ®ion, WindowPaintData& data) override;
|
void finalDrawWindow(EffectWindowImpl* w, int mask, const QRegion ®ion, WindowPaintData& data) override;
|
||||||
void updateProjectionMatrix() override;
|
void updateProjectionMatrix() override;
|
||||||
void paintCursor() override;
|
void paintCursor(const QRegion ®ion) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void performPaintWindow(EffectWindowImpl* w, int mask, const QRegion ®ion, WindowPaintData& data);
|
void performPaintWindow(EffectWindowImpl* w, int mask, const QRegion ®ion, WindowPaintData& data);
|
||||||
|
|
|
@ -110,7 +110,7 @@ qint64 SceneQPainter::paint(const QRegion &_damage, const QList<Toplevel *> &top
|
||||||
QRegion updateRegion, validRegion;
|
QRegion updateRegion, validRegion;
|
||||||
paintScreen(&mask, damage.intersected(geometry), QRegion(), &updateRegion, &validRegion);
|
paintScreen(&mask, damage.intersected(geometry), QRegion(), &updateRegion, &validRegion);
|
||||||
overallUpdate = overallUpdate.united(updateRegion);
|
overallUpdate = overallUpdate.united(updateRegion);
|
||||||
paintCursor();
|
paintCursor(updateRegion);
|
||||||
|
|
||||||
m_painter->restore();
|
m_painter->restore();
|
||||||
m_painter->end();
|
m_painter->end();
|
||||||
|
@ -128,7 +128,7 @@ qint64 SceneQPainter::paint(const QRegion &_damage, const QList<Toplevel *> &top
|
||||||
QRegion updateRegion, validRegion;
|
QRegion updateRegion, validRegion;
|
||||||
paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion);
|
paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion);
|
||||||
|
|
||||||
paintCursor();
|
paintCursor(updateRegion);
|
||||||
m_backend->showOverlay();
|
m_backend->showOverlay();
|
||||||
|
|
||||||
m_painter->end();
|
m_painter->end();
|
||||||
|
@ -149,7 +149,7 @@ void SceneQPainter::paintBackground(const QRegion ®ion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneQPainter::paintCursor()
|
void SceneQPainter::paintCursor(const QRegion &rendered)
|
||||||
{
|
{
|
||||||
if (!kwinApp()->platform()->usesSoftwareCursor()) {
|
if (!kwinApp()->platform()->usesSoftwareCursor()) {
|
||||||
return;
|
return;
|
||||||
|
@ -160,9 +160,11 @@ void SceneQPainter::paintCursor()
|
||||||
if (img.isNull()) {
|
if (img.isNull()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const QPoint cursorPos = cursor->pos();
|
|
||||||
const QPoint hotspot = cursor->hotspot();
|
m_painter->save();
|
||||||
m_painter->drawImage(cursorPos - hotspot, img);
|
m_painter->setClipRegion(rendered.intersected(cursor->geometry()));
|
||||||
|
m_painter->drawImage(cursor->geometry(), img);
|
||||||
|
m_painter->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneQPainter::paintEffectQuickView(EffectQuickView *w)
|
void SceneQPainter::paintEffectQuickView(EffectQuickView *w)
|
||||||
|
|
|
@ -50,7 +50,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void paintBackground(const QRegion ®ion) override;
|
void paintBackground(const QRegion ®ion) override;
|
||||||
Scene::Window *createWindow(Toplevel *toplevel) override;
|
Scene::Window *createWindow(Toplevel *toplevel) override;
|
||||||
void paintCursor() override;
|
void paintCursor(const QRegion ®ion) override;
|
||||||
void paintEffectQuickView(EffectQuickView *w) override;
|
void paintEffectQuickView(EffectQuickView *w) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1326,9 +1326,9 @@ Scene *XRenderFactory::create(QObject *parent) const
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void KWin::SceneXrender::paintCursor()
|
void KWin::SceneXrender::paintCursor(const QRegion ®ion)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(region)
|
||||||
}
|
}
|
||||||
|
|
||||||
void KWin::SceneXrender::paintEffectQuickView(KWin::EffectQuickView *w)
|
void KWin::SceneXrender::paintEffectQuickView(KWin::EffectQuickView *w)
|
||||||
|
|
|
@ -166,7 +166,7 @@ protected:
|
||||||
void paintBackground(const QRegion ®ion) override;
|
void paintBackground(const QRegion ®ion) override;
|
||||||
void paintGenericScreen(int mask, const ScreenPaintData &data) override;
|
void paintGenericScreen(int mask, const ScreenPaintData &data) override;
|
||||||
void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data) override;
|
void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data) override;
|
||||||
void paintCursor() override;
|
void paintCursor(const QRegion ®ion) override;
|
||||||
void paintEffectQuickView(EffectQuickView *w) override;
|
void paintEffectQuickView(EffectQuickView *w) override;
|
||||||
private:
|
private:
|
||||||
explicit SceneXrender(XRenderBackend *backend, QObject *parent = nullptr);
|
explicit SceneXrender(XRenderBackend *backend, QObject *parent = nullptr);
|
||||||
|
|
2
scene.h
2
scene.h
|
@ -208,7 +208,7 @@ protected:
|
||||||
void paintScreen(int *mask, const QRegion &damage, const QRegion &repaint,
|
void paintScreen(int *mask, const QRegion &damage, const QRegion &repaint,
|
||||||
QRegion *updateRegion, QRegion *validRegion, const QMatrix4x4 &projection = QMatrix4x4(), const QRect &outputGeometry = QRect(), const qreal screenScale = 1.0);
|
QRegion *updateRegion, QRegion *validRegion, const QMatrix4x4 &projection = QMatrix4x4(), const QRect &outputGeometry = QRect(), const qreal screenScale = 1.0);
|
||||||
// Render cursor texture in case hardware cursor is disabled/non-applicable
|
// Render cursor texture in case hardware cursor is disabled/non-applicable
|
||||||
virtual void paintCursor() = 0;
|
virtual void paintCursor(const QRegion ®ion) = 0;
|
||||||
friend class EffectsHandlerImpl;
|
friend class EffectsHandlerImpl;
|
||||||
// called after all effects had their paintScreen() called
|
// called after all effects had their paintScreen() called
|
||||||
void finalPaintScreen(int mask, const QRegion ®ion, ScreenPaintData& data);
|
void finalPaintScreen(int mask, const QRegion ®ion, ScreenPaintData& data);
|
||||||
|
|
Loading…
Reference in a new issue