2022-02-05 09:47:00 +00:00
|
|
|
/*
|
|
|
|
SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
|
|
|
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
|
|
|
|
2022-04-12 13:14:23 +00:00
|
|
|
#include "cursordelegate_opengl.h"
|
2022-12-19 08:45:29 +00:00
|
|
|
#include "composite.h"
|
2022-08-29 07:55:49 +00:00
|
|
|
#include "core/renderlayer.h"
|
|
|
|
#include "core/rendertarget.h"
|
2022-02-05 09:47:00 +00:00
|
|
|
#include "cursor.h"
|
|
|
|
#include "kwingltexture.h"
|
|
|
|
#include "kwinglutils.h"
|
2022-12-19 08:45:29 +00:00
|
|
|
#include "scene/cursorscene.h"
|
2022-02-05 09:47:00 +00:00
|
|
|
|
2023-02-20 15:22:24 +00:00
|
|
|
#include <cmath>
|
|
|
|
|
2022-02-05 09:47:00 +00:00
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
2022-04-12 13:14:23 +00:00
|
|
|
CursorDelegateOpenGL::~CursorDelegateOpenGL()
|
2022-02-05 09:47:00 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-04-12 13:14:23 +00:00
|
|
|
void CursorDelegateOpenGL::paint(RenderTarget *renderTarget, const QRegion ®ion)
|
2022-02-05 09:47:00 +00:00
|
|
|
{
|
2023-02-19 23:35:44 +00:00
|
|
|
if (!region.intersects(layer()->mapToGlobal(layer()->rect()).toAlignedRect())) {
|
2022-04-12 13:14:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-19 08:45:29 +00:00
|
|
|
// Render the cursor scene in an offscreen render target.
|
2023-02-19 23:35:44 +00:00
|
|
|
const QSize bufferSize = (Cursors::self()->currentCursor()->rect().size() * renderTarget->devicePixelRatio()).toSize();
|
2022-12-19 08:45:29 +00:00
|
|
|
if (!m_texture || m_texture->size() != bufferSize) {
|
|
|
|
m_texture = std::make_unique<GLTexture>(GL_RGBA8, bufferSize);
|
|
|
|
m_framebuffer = std::make_unique<GLFramebuffer>(m_texture.get());
|
|
|
|
}
|
2022-02-05 09:47:00 +00:00
|
|
|
|
2022-12-19 08:45:29 +00:00
|
|
|
RenderTarget offscreenRenderTarget(m_framebuffer.get());
|
|
|
|
offscreenRenderTarget.setDevicePixelRatio(renderTarget->devicePixelRatio());
|
2022-02-05 09:47:00 +00:00
|
|
|
|
2022-12-19 08:45:29 +00:00
|
|
|
RenderLayer renderLayer(layer()->loop());
|
|
|
|
renderLayer.setDelegate(std::make_unique<SceneDelegate>(Compositor::self()->cursorScene()));
|
|
|
|
renderLayer.delegate()->prePaint();
|
|
|
|
renderLayer.delegate()->paint(&offscreenRenderTarget, infiniteRegion());
|
|
|
|
renderLayer.delegate()->postPaint();
|
2022-02-05 09:47:00 +00:00
|
|
|
|
2022-12-19 08:45:29 +00:00
|
|
|
// Show the rendered cursor scene on the screen.
|
2023-02-19 23:35:44 +00:00
|
|
|
const QRectF cursorRect = layer()->mapToGlobal(layer()->rect());
|
2022-08-18 10:16:53 +00:00
|
|
|
const qreal scale = renderTarget->devicePixelRatio();
|
2022-02-05 09:47:00 +00:00
|
|
|
|
|
|
|
QMatrix4x4 mvp;
|
2022-08-18 10:16:53 +00:00
|
|
|
mvp.ortho(QRect(QPoint(0, 0), renderTarget->size()));
|
2023-02-20 15:22:24 +00:00
|
|
|
mvp.translate(std::round(cursorRect.x() * scale), std::round(cursorRect.y() * scale));
|
2022-02-05 09:47:00 +00:00
|
|
|
|
2022-12-20 15:48:05 +00:00
|
|
|
GLFramebuffer *fbo = std::get<GLFramebuffer *>(renderTarget->nativeHandle());
|
|
|
|
GLFramebuffer::pushFramebuffer(fbo);
|
|
|
|
|
2022-02-05 09:47:00 +00:00
|
|
|
// 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);
|
|
|
|
|
2022-12-19 08:45:29 +00:00
|
|
|
m_texture->bind();
|
2022-02-05 09:47:00 +00:00
|
|
|
ShaderBinder binder(ShaderTrait::MapTexture);
|
|
|
|
binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
|
2023-02-19 00:04:22 +00:00
|
|
|
m_texture->render(region, cursorRect.size(), scale);
|
2022-12-19 08:45:29 +00:00
|
|
|
m_texture->unbind();
|
2022-02-05 09:47:00 +00:00
|
|
|
glDisable(GL_BLEND);
|
2022-12-20 15:48:05 +00:00
|
|
|
|
|
|
|
GLFramebuffer::popFramebuffer();
|
2022-02-05 09:47:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace KWin
|