File indexing completed on 2024-04-28 16:48:41

0001 /*
0002     SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "cursordelegate_opengl.h"
0008 #include "composite.h"
0009 #include "core/renderlayer.h"
0010 #include "core/rendertarget.h"
0011 #include "cursor.h"
0012 #include "kwingltexture.h"
0013 #include "kwinglutils.h"
0014 #include "scene/cursorscene.h"
0015 
0016 #include <cmath>
0017 
0018 namespace KWin
0019 {
0020 
0021 CursorDelegateOpenGL::~CursorDelegateOpenGL()
0022 {
0023 }
0024 
0025 void CursorDelegateOpenGL::paint(RenderTarget *renderTarget, const QRegion &region)
0026 {
0027     if (!region.intersects(layer()->mapToGlobal(layer()->rect()))) {
0028         return;
0029     }
0030 
0031     // Render the cursor scene in an offscreen render target.
0032     const QSize bufferSize = Cursors::self()->currentCursor()->rect().size() * renderTarget->devicePixelRatio();
0033     if (!m_texture || m_texture->size() != bufferSize) {
0034         m_texture = std::make_unique<GLTexture>(GL_RGBA8, bufferSize);
0035         m_framebuffer = std::make_unique<GLFramebuffer>(m_texture.get());
0036     }
0037 
0038     RenderTarget offscreenRenderTarget(m_framebuffer.get());
0039     offscreenRenderTarget.setDevicePixelRatio(renderTarget->devicePixelRatio());
0040 
0041     RenderLayer renderLayer(layer()->loop());
0042     renderLayer.setDelegate(std::make_unique<SceneDelegate>(Compositor::self()->cursorScene()));
0043     renderLayer.delegate()->prePaint();
0044     renderLayer.delegate()->paint(&offscreenRenderTarget, infiniteRegion());
0045     renderLayer.delegate()->postPaint();
0046 
0047     // Show the rendered cursor scene on the screen.
0048     const QRect cursorRect = layer()->mapToGlobal(layer()->rect());
0049     const qreal scale = renderTarget->devicePixelRatio();
0050 
0051     QMatrix4x4 mvp;
0052     mvp.ortho(QRect(QPoint(0, 0), renderTarget->size()));
0053     mvp.translate(std::round(cursorRect.x() * scale), std::round(cursorRect.y() * scale));
0054 
0055     GLFramebuffer *fbo = std::get<GLFramebuffer *>(renderTarget->nativeHandle());
0056     GLFramebuffer::pushFramebuffer(fbo);
0057 
0058     // Don't need to call GLVertexBuffer::beginFrame() and GLVertexBuffer::endOfFrame() because
0059     // the GLVertexBuffer::streamingBuffer() is not being used when painting cursor.
0060     glEnable(GL_BLEND);
0061     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
0062 
0063     m_texture->bind();
0064     ShaderBinder binder(ShaderTrait::MapTexture);
0065     binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, mvp);
0066     m_texture->render(region, QRect(0, 0, cursorRect.width(), cursorRect.height()), scale);
0067     m_texture->unbind();
0068     glDisable(GL_BLEND);
0069 
0070     GLFramebuffer::popFramebuffer();
0071 }
0072 
0073 } // namespace KWin