File indexing completed on 2024-09-08 13:19:47
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 ®ion) 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