Port software cursor to RenderLayer
Software cursor has always been a major source of problems. Hopefully, porting it to RenderLayer will help us with that. Note that the cursor layer is currently visible only when using software cursor, however it will be changed once the Compositor can allocate a real hardware cursor plane. Currently, software cursor uses graphics-specific APIs (OpenGL and QPainter) to paint itself. That will be changed in the future when rendering parts are extracted from the Scene in a reusable helper.
This commit is contained in:
parent
8739258f2f
commit
dd6d0b22cc
17 changed files with 313 additions and 124 deletions
|
@ -36,6 +36,9 @@ target_sources(kwin PRIVATE
|
|||
client_machine.cpp
|
||||
composite.cpp
|
||||
cursor.cpp
|
||||
cursorview.cpp
|
||||
cursorview_opengl.cpp
|
||||
cursorview_qpainter.cpp
|
||||
dbusinterface.cpp
|
||||
debug_console.cpp
|
||||
decorationitem.cpp
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
*/
|
||||
#include "composite.h"
|
||||
#include "abstract_output.h"
|
||||
#include "cursorview_opengl.h"
|
||||
#include "cursorview_qpainter.h"
|
||||
#include "dbusinterface.h"
|
||||
#include "x11client.h"
|
||||
#include "decorations/decoratedclient.h"
|
||||
|
@ -191,6 +193,7 @@ bool Compositor::attemptOpenGLCompositing()
|
|||
|
||||
m_backend = backend.take();
|
||||
m_scene = scene.take();
|
||||
m_cursorView = new OpenGLCursorView();
|
||||
|
||||
// set strict binding
|
||||
if (options->isGlStrictBindingFollowsDriver()) {
|
||||
|
@ -215,6 +218,7 @@ bool Compositor::attemptQPainterCompositing()
|
|||
|
||||
m_backend = backend.take();
|
||||
m_scene = scene.take();
|
||||
m_cursorView = new QPainterCursorView();
|
||||
|
||||
qCDebug(KWIN_CORE) << "QPainter compositing has been successfully initialized";
|
||||
return true;
|
||||
|
@ -412,12 +416,33 @@ AbstractOutput *Compositor::findOutput(RenderLoop *loop) const
|
|||
|
||||
void Compositor::addOutput(AbstractOutput *output)
|
||||
{
|
||||
Q_ASSERT(kwinApp()->operationMode() != Application::OperationModeX11);
|
||||
|
||||
auto workspaceLayer = new RenderLayer(output->renderLoop());
|
||||
workspaceLayer->setDelegate(new SceneDelegate(m_scene, output));
|
||||
workspaceLayer->setGeometry(output->geometry());
|
||||
connect(output, &AbstractOutput::geometryChanged, this, [output, workspaceLayer]() {
|
||||
workspaceLayer->setGeometry(output->geometry());
|
||||
});
|
||||
|
||||
auto cursorLayer = new RenderLayer(output->renderLoop());
|
||||
cursorLayer->setVisible(false);
|
||||
cursorLayer->setDelegate(new CursorDelegate(output, m_cursorView));
|
||||
cursorLayer->setParent(workspaceLayer);
|
||||
cursorLayer->setSuperlayer(workspaceLayer);
|
||||
|
||||
auto updateCursorLayer = [output, workspaceLayer, cursorLayer]() {
|
||||
const Cursor *cursor = Cursors::self()->currentCursor();
|
||||
cursorLayer->setVisible(cursor->isOnOutput(output) && output->usesSoftwareCursor());
|
||||
cursorLayer->setGeometry(workspaceLayer->mapFromGlobal(cursor->geometry()));
|
||||
cursorLayer->addRepaintFull();
|
||||
};
|
||||
updateCursorLayer();
|
||||
connect(output, &AbstractOutput::geometryChanged, cursorLayer, updateCursorLayer);
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, cursorLayer, updateCursorLayer);
|
||||
connect(Cursors::self(), &Cursors::hiddenChanged, cursorLayer, updateCursorLayer);
|
||||
connect(Cursors::self(), &Cursors::positionChanged, cursorLayer, updateCursorLayer);
|
||||
|
||||
addSuperLayer(workspaceLayer);
|
||||
}
|
||||
|
||||
|
@ -512,6 +537,9 @@ void Compositor::stop()
|
|||
delete m_scene;
|
||||
m_scene = nullptr;
|
||||
|
||||
delete m_cursorView;
|
||||
m_cursorView = nullptr;
|
||||
|
||||
delete m_backend;
|
||||
m_backend = nullptr;
|
||||
|
||||
|
@ -646,6 +674,19 @@ void Compositor::composite(RenderLoop *renderLoop)
|
|||
}
|
||||
|
||||
postPaintPass(superLayer);
|
||||
|
||||
// TODO: Put it inside the cursor layer once the cursor layer can be backed by a real output layer.
|
||||
if (waylandServer()) {
|
||||
const std::chrono::milliseconds frameTime =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(output->renderLoop()->lastPresentationTimestamp());
|
||||
|
||||
if (!Cursors::self()->isCursorHidden()) {
|
||||
Cursor *cursor = Cursors::self()->currentCursor();
|
||||
if (cursor->geometry().intersects(output->geometry())) {
|
||||
cursor->markAsRendered(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Compositor::prePaintPass(RenderLayer *layer)
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace KWin
|
|||
|
||||
class AbstractOutput;
|
||||
class CompositorSelectionOwner;
|
||||
class CursorView;
|
||||
class RenderBackend;
|
||||
class RenderLayer;
|
||||
class RenderLoop;
|
||||
|
@ -148,6 +149,7 @@ private:
|
|||
QList<xcb_atom_t> m_unusedSupportProperties;
|
||||
QTimer m_unusedSupportPropertyTimer;
|
||||
Scene *m_scene = nullptr;
|
||||
CursorView *m_cursorView = nullptr;
|
||||
RenderBackend *m_backend = nullptr;
|
||||
QHash<RenderLoop *, RenderLayer *> m_superlayers;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "cursor.h"
|
||||
// kwin
|
||||
#include "abstract_output.h"
|
||||
#include "input.h"
|
||||
#include "keyboard_input.h"
|
||||
#include "main.h"
|
||||
|
@ -167,6 +168,17 @@ void Cursor::slotKGlobalSettingsNotifyChange(int type, int arg)
|
|||
}
|
||||
}
|
||||
|
||||
bool Cursor::isOnOutput(AbstractOutput *output) const
|
||||
{
|
||||
if (Cursors::self()->isCursorHidden()) {
|
||||
return false;
|
||||
}
|
||||
if (!geometry().intersects(output->geometry())) {
|
||||
return false;
|
||||
}
|
||||
return !image().isNull();
|
||||
}
|
||||
|
||||
QRect Cursor::geometry() const
|
||||
{
|
||||
return rect().translated(m_pos - hotspot());
|
||||
|
|
|
@ -24,6 +24,8 @@ class QTimer;
|
|||
namespace KWin
|
||||
{
|
||||
|
||||
class AbstractOutput;
|
||||
|
||||
namespace ExtendedCursor {
|
||||
/**
|
||||
* Extension of Qt::CursorShape with values not currently present there
|
||||
|
@ -165,6 +167,11 @@ public:
|
|||
QRect geometry() const;
|
||||
QRect rect() const;
|
||||
|
||||
/**
|
||||
* Returns @c true if the cursor is visible on the given output; otherwise returns @c false.
|
||||
*/
|
||||
bool isOnOutput(AbstractOutput *output) const;
|
||||
|
||||
void updateCursor(const QImage &image, const QPoint &hotspot);
|
||||
void markAsRendered(std::chrono::milliseconds timestamp);
|
||||
|
||||
|
|
40
src/cursorview.cpp
Normal file
40
src/cursorview.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "cursorview.h"
|
||||
#include "abstract_output.h"
|
||||
#include "cursor.h"
|
||||
#include "renderlayer.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
CursorView::CursorView(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
CursorDelegate::CursorDelegate(AbstractOutput *output, CursorView *view)
|
||||
: m_view(view)
|
||||
, m_output(output)
|
||||
{
|
||||
}
|
||||
|
||||
void CursorDelegate::paint(const QRegion &damage, const QRegion &repaint, QRegion &update, QRegion &valid)
|
||||
{
|
||||
const Cursor *cursor = Cursors::self()->currentCursor();
|
||||
const QRegion cursorDamage = damage.intersected(cursor->geometry());
|
||||
const QRegion cursorRepaint = repaint.intersected(cursor->geometry());
|
||||
|
||||
update = cursorDamage;
|
||||
valid = cursorDamage.united(cursorRepaint);
|
||||
|
||||
if (!valid.isEmpty()) {
|
||||
m_view->paint(m_output, valid);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KWin
|
40
src/cursorview.h
Normal file
40
src/cursorview.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "renderlayerdelegate.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class AbstractOutput;
|
||||
|
||||
class KWIN_EXPORT CursorView : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CursorView(QObject *parent = nullptr);
|
||||
|
||||
virtual void paint(AbstractOutput *output, const QRegion ®ion) = 0;
|
||||
};
|
||||
|
||||
class KWIN_EXPORT CursorDelegate : public RenderLayerDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CursorDelegate(AbstractOutput *output, CursorView *view);
|
||||
|
||||
void paint(const QRegion &damage, const QRegion &repaint, QRegion &update, QRegion &valid) override;
|
||||
|
||||
private:
|
||||
CursorView *m_view;
|
||||
AbstractOutput *m_output;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
76
src/cursorview_opengl.cpp
Normal file
76
src/cursorview_opengl.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "cursorview_opengl.h"
|
||||
#include "abstract_output.h"
|
||||
#include "cursor.h"
|
||||
#include "kwingltexture.h"
|
||||
#include "kwinglutils.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
OpenGLCursorView::OpenGLCursorView(QObject *parent)
|
||||
: CursorView(parent)
|
||||
{
|
||||
}
|
||||
|
||||
OpenGLCursorView::~OpenGLCursorView()
|
||||
{
|
||||
}
|
||||
|
||||
void OpenGLCursorView::paint(AbstractOutput *output, const QRegion ®ion)
|
||||
{
|
||||
const Cursor *cursor = Cursors::self()->currentCursor();
|
||||
auto allocateTexture = [this]() {
|
||||
const QImage img = Cursors::self()->currentCursor()->image();
|
||||
if (img.isNull()) {
|
||||
m_cursorTextureDirty = false;
|
||||
return;
|
||||
}
|
||||
m_cursorTexture.reset(new GLTexture(img));
|
||||
m_cursorTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
m_cursorTextureDirty = false;
|
||||
};
|
||||
|
||||
// lazy init texture cursor only in case we need software rendering
|
||||
if (!m_cursorTexture) {
|
||||
allocateTexture();
|
||||
|
||||
// handle shape update on case cursor image changed
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, [this]() {
|
||||
m_cursorTextureDirty = true;
|
||||
});
|
||||
} else if (m_cursorTextureDirty) {
|
||||
const QImage image = Cursors::self()->currentCursor()->image();
|
||||
if (image.size() == m_cursorTexture->size()) {
|
||||
m_cursorTexture->update(image);
|
||||
m_cursorTextureDirty = false;
|
||||
} else {
|
||||
allocateTexture();
|
||||
}
|
||||
}
|
||||
|
||||
const QRect cursorRect = cursor->geometry();
|
||||
|
||||
QMatrix4x4 mvp;
|
||||
mvp.ortho(output->geometry());
|
||||
mvp.translate(cursorRect.x(), cursorRect.y());
|
||||
|
||||
// Don't need to call GLVertexBuffer::beginFrame() and GLVertexBuffer::endOfFrame() because
|
||||
// the GLVertexBuffer::streamingBuffer() is not being used when painting cursor.
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
m_cursorTexture->bind();
|
||||
ShaderBinder binder(ShaderTrait::MapTexture);
|
||||
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
|
||||
m_cursorTexture->render(region, QRect(0, 0, cursorRect.width(), cursorRect.height()));
|
||||
m_cursorTexture->unbind();
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
} // namespace KWin
|
31
src/cursorview_opengl.h
Normal file
31
src/cursorview_opengl.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cursorview.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class GLTexture;
|
||||
|
||||
class OpenGLCursorView final : public CursorView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OpenGLCursorView(QObject *parent = nullptr);
|
||||
~OpenGLCursorView() override;
|
||||
|
||||
void paint(AbstractOutput *output, const QRegion ®ion) override;
|
||||
|
||||
private:
|
||||
QScopedPointer<GLTexture> m_cursorTexture;
|
||||
bool m_cursorTextureDirty = false;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
37
src/cursorview_qpainter.cpp
Normal file
37
src/cursorview_qpainter.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "cursorview_qpainter.h"
|
||||
#include "abstract_output.h"
|
||||
#include "composite.h"
|
||||
#include "cursor.h"
|
||||
#include "qpainterbackend.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
QPainterCursorView::QPainterCursorView(QObject *parent)
|
||||
: CursorView(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void QPainterCursorView::paint(AbstractOutput *output, const QRegion ®ion)
|
||||
{
|
||||
QImage *renderTarget = static_cast<QPainterBackend *>(Compositor::self()->backend())->bufferForScreen(output);
|
||||
if (Q_UNLIKELY(!renderTarget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Cursor *cursor = Cursors::self()->currentCursor();
|
||||
QPainter painter(renderTarget);
|
||||
painter.setWindow(output->geometry());
|
||||
painter.setClipRegion(region);
|
||||
painter.drawImage(cursor->geometry(), cursor->image());
|
||||
}
|
||||
|
||||
} // namespace KWin
|
24
src/cursorview_qpainter.h
Normal file
24
src/cursorview_qpainter.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cursorview.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class QPainterCursorView final : public CursorView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QPainterCursorView(QObject *parent = nullptr);
|
||||
|
||||
void paint(AbstractOutput *output, const QRegion ®ion) override;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
|
@ -148,23 +148,6 @@ void Scene::initialize()
|
|||
connect(workspace(), &Workspace::geometryChanged, this, [this]() {
|
||||
setGeometry(workspace()->geometry());
|
||||
});
|
||||
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, &Scene::addCursorRepaints);
|
||||
connect(Cursors::self(), &Cursors::positionChanged, this, &Scene::addCursorRepaints);
|
||||
}
|
||||
|
||||
void Scene::addCursorRepaints()
|
||||
{
|
||||
const auto outputs = kwinApp()->platform()->enabledOutputs();
|
||||
QRegion repaintRegion = Cursors::self()->currentCursor()->geometry();
|
||||
repaintRegion |= m_lastCursorGeometry;
|
||||
for (const auto &output : outputs) {
|
||||
auto intersection = repaintRegion.intersected(output->geometry());
|
||||
if (!intersection.isEmpty() && output->usesSoftwareCursor()) {
|
||||
addRepaint(intersection);
|
||||
}
|
||||
}
|
||||
m_lastCursorGeometry = Cursors::self()->currentCursor()->geometry();
|
||||
}
|
||||
|
||||
void Scene::addRepaintFull()
|
||||
|
@ -297,12 +280,6 @@ void Scene::postPaint()
|
|||
surface->frameRendered(frameTime.count());
|
||||
}
|
||||
}
|
||||
if (!Cursors::self()->isCursorHidden()) {
|
||||
Cursor *cursor = Cursors::self()->currentCursor();
|
||||
if (cursor->geometry().intersects(painted_screen->geometry())) {
|
||||
cursor->markAsRendered(frameTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearStackingOrder();
|
||||
|
|
|
@ -224,8 +224,6 @@ protected:
|
|||
// shared implementation, starts painting the screen
|
||||
void paintScreen(const QRegion &damage, const QRegion &repaint,
|
||||
QRegion *updateRegion, QRegion *validRegion);
|
||||
// Render cursor texture in case hardware cursor is disabled/non-applicable
|
||||
virtual void paintCursor(AbstractOutput *output, const QRegion ®ion) = 0;
|
||||
friend class EffectsHandlerImpl;
|
||||
// called after all effects had their paintScreen() called
|
||||
void finalPaintScreen(int mask, const QRegion ®ion, ScreenPaintData& data);
|
||||
|
@ -278,8 +276,6 @@ protected:
|
|||
// windows in their stacking order
|
||||
QVector< Window* > stacking_order;
|
||||
private:
|
||||
void addCursorRepaints();
|
||||
|
||||
std::chrono::milliseconds m_expectedPresentTimestamp = std::chrono::milliseconds::zero();
|
||||
QList<SceneDelegate *> m_delegates;
|
||||
QHash< Toplevel*, Window* > m_windows;
|
||||
|
@ -289,7 +285,6 @@ private:
|
|||
qreal m_renderTargetScale = 1;
|
||||
// how many times finalPaintScreen() has been called
|
||||
int m_paintScreenCount = 0;
|
||||
QRect m_lastCursorGeometry;
|
||||
};
|
||||
|
||||
// The base class for windows representations in composite backends
|
||||
|
|
|
@ -97,78 +97,6 @@ bool SceneOpenGL::initFailed() const
|
|||
return !init_ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render cursor texture in case hardware cursor is disabled.
|
||||
* Useful for screen recording apps or backends that can't do planes.
|
||||
*/
|
||||
void SceneOpenGL::paintCursor(AbstractOutput *output, const QRegion &rendered)
|
||||
{
|
||||
Cursor* cursor = Cursors::self()->currentCursor();
|
||||
|
||||
// don't paint if we use hardware cursor or the cursor is hidden
|
||||
if (!output || !output->usesSoftwareCursor()
|
||||
|| Cursors::self()->isCursorHidden()
|
||||
|| cursor->image().isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// figure out which part of the cursor needs to be repainted
|
||||
const QPoint cursorPos = cursor->pos() - cursor->hotspot();
|
||||
const QRect cursorRect = cursor->rect();
|
||||
QRegion region;
|
||||
for (const QRect &rect : rendered) {
|
||||
region |= rect.translated(-cursorPos).intersected(cursorRect);
|
||||
}
|
||||
if (region.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto newTexture = [this] {
|
||||
const QImage img = Cursors::self()->currentCursor()->image();
|
||||
if (img.isNull()) {
|
||||
m_cursorTextureDirty = false;
|
||||
return;
|
||||
}
|
||||
m_cursorTexture.reset(new GLTexture(img));
|
||||
m_cursorTexture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
m_cursorTextureDirty = false;
|
||||
};
|
||||
|
||||
// lazy init texture cursor only in case we need software rendering
|
||||
if (!m_cursorTexture) {
|
||||
newTexture();
|
||||
|
||||
// handle shape update on case cursor image changed
|
||||
connect(Cursors::self(), &Cursors::currentCursorChanged, this, [this] {
|
||||
m_cursorTextureDirty = true;
|
||||
});
|
||||
} else if (m_cursorTextureDirty) {
|
||||
const QImage image = Cursors::self()->currentCursor()->image();
|
||||
if (image.size() == m_cursorTexture->size()) {
|
||||
m_cursorTexture->update(image);
|
||||
m_cursorTextureDirty = false;
|
||||
} else {
|
||||
newTexture();
|
||||
}
|
||||
}
|
||||
|
||||
// get cursor position in projection coordinates
|
||||
QMatrix4x4 mvp = renderTargetProjectionMatrix();
|
||||
mvp.translate(cursorPos.x(), cursorPos.y());
|
||||
|
||||
// handle transparence
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// paint texture in cursor offset
|
||||
m_cursorTexture->bind();
|
||||
ShaderBinder binder(ShaderTrait::MapTexture);
|
||||
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
|
||||
m_cursorTexture->render(cursorRect);
|
||||
m_cursorTexture->unbind();
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void SceneOpenGL::aboutToStartPainting(AbstractOutput *output, const QRegion &damage)
|
||||
{
|
||||
m_backend->aboutToStartPainting(output, damage);
|
||||
|
@ -178,7 +106,6 @@ void SceneOpenGL::paint(const QRegion &damage, const QRegion &repaint, QRegion &
|
|||
{
|
||||
GLVertexBuffer::streamingBuffer()->beginFrame();
|
||||
paintScreen(damage, repaint, &update, &valid);
|
||||
paintCursor(painted_screen, valid);
|
||||
GLVertexBuffer::streamingBuffer()->endOfFrame();
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@ protected:
|
|||
void paintGenericScreen(int mask, const ScreenPaintData &data) override;
|
||||
Scene::Window *createWindow(Toplevel *t) override;
|
||||
void finalDrawWindow(EffectWindowImpl* w, int mask, const QRegion ®ion, WindowPaintData& data) override;
|
||||
void paintCursor(AbstractOutput *output, const QRegion ®ion) override;
|
||||
|
||||
private:
|
||||
void doPaintBackground(const QVector< float >& vertices);
|
||||
|
@ -78,8 +77,6 @@ private:
|
|||
bool init_ok = true;
|
||||
OpenGLBackend *m_backend;
|
||||
LanczosFilter *m_lanczosFilter = nullptr;
|
||||
QScopedPointer<GLTexture> m_cursorTexture;
|
||||
bool m_cursorTextureDirty = false;
|
||||
QMatrix4x4 m_screenProjectionMatrix;
|
||||
GLuint vao = 0;
|
||||
};
|
||||
|
|
|
@ -75,7 +75,6 @@ void SceneQPainter::paint(const QRegion &damage, const QRegion &repaint, QRegion
|
|||
m_painter->begin(buffer);
|
||||
m_painter->setWindow(painted_screen->geometry());
|
||||
paintScreen(damage, repaint, &update, &valid);
|
||||
paintCursor(painted_screen, update);
|
||||
m_painter->end();
|
||||
}
|
||||
}
|
||||
|
@ -87,24 +86,6 @@ void SceneQPainter::paintBackground(const QRegion ®ion)
|
|||
}
|
||||
}
|
||||
|
||||
void SceneQPainter::paintCursor(AbstractOutput *output, const QRegion &rendered)
|
||||
{
|
||||
if (!output || !output->usesSoftwareCursor() || Cursors::self()->isCursorHidden()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cursor* cursor = Cursors::self()->currentCursor();
|
||||
const QImage img = cursor->image();
|
||||
if (img.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_painter->save();
|
||||
m_painter->setClipRegion(rendered.intersected(cursor->geometry()));
|
||||
m_painter->drawImage(cursor->geometry(), img);
|
||||
m_painter->restore();
|
||||
}
|
||||
|
||||
void SceneQPainter::paintOffscreenQuickView(OffscreenQuickView *w)
|
||||
{
|
||||
QPainter *painter = effects->scenePainter();
|
||||
|
|
|
@ -48,7 +48,6 @@ public:
|
|||
protected:
|
||||
void paintBackground(const QRegion ®ion) override;
|
||||
Scene::Window *createWindow(Toplevel *toplevel) override;
|
||||
void paintCursor(AbstractOutput *output, const QRegion ®ion) override;
|
||||
void paintOffscreenQuickView(OffscreenQuickView *w) override;
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue