kwin/src/cursordelegate_opengl.cpp
Vlad Zahorodnii bd689ef76c Simplify software cursor implementation
With RenderTarget, CursorView and CursorDelegate can be merged.
2022-04-13 10:16:16 +00:00

80 lines
2.4 KiB
C++

/*
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "cursordelegate_opengl.h"
#include "cursor.h"
#include "kwingltexture.h"
#include "kwinglutils.h"
#include "renderlayer.h"
#include "rendertarget.h"
namespace KWin
{
CursorDelegateOpenGL::CursorDelegateOpenGL(QObject *parent)
: RenderLayerDelegate(parent)
{
}
CursorDelegateOpenGL::~CursorDelegateOpenGL()
{
}
void CursorDelegateOpenGL::paint(RenderTarget *renderTarget, const QRegion &region)
{
if (!region.intersects(layer()->mapToGlobal(layer()->rect()))) {
return;
}
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 = layer()->mapToGlobal(layer()->rect());
QMatrix4x4 mvp;
mvp.ortho(QRect(QPoint(0, 0), renderTarget->size() / renderTarget->devicePixelRatio()));
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