File indexing completed on 2024-11-10 04:57:14
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 "scene/cursordelegate_opengl.h" 0008 #include "compositor.h" 0009 #include "core/output.h" 0010 #include "core/pixelgrid.h" 0011 #include "core/renderlayer.h" 0012 #include "core/rendertarget.h" 0013 #include "core/renderviewport.h" 0014 #include "cursor.h" 0015 #include "opengl/gltexture.h" 0016 #include "opengl/glutils.h" 0017 #include "scene/cursorscene.h" 0018 0019 #include <cmath> 0020 0021 namespace KWin 0022 { 0023 0024 CursorDelegateOpenGL::CursorDelegateOpenGL(Output *output) 0025 : m_output(output) 0026 { 0027 } 0028 0029 CursorDelegateOpenGL::~CursorDelegateOpenGL() 0030 { 0031 } 0032 0033 void CursorDelegateOpenGL::paint(const RenderTarget &renderTarget, const QRegion ®ion) 0034 { 0035 const QRegion dirty = region.intersected(layer()->mapToGlobal(layer()->rect()).toAlignedRect()); 0036 if (dirty.isEmpty()) { 0037 return; 0038 } 0039 0040 // Show the rendered cursor scene on the screen. 0041 const QRect cursorRect = snapToPixelGrid(scaledRect(layer()->mapToGlobal(layer()->rect()), m_output->scale())); 0042 0043 // Render the cursor scene in an offscreen render target. 0044 const QSize bufferSize = cursorRect.size(); 0045 const GLenum bufferFormat = renderTarget.colorDescription() == ColorDescription::sRGB ? GL_RGBA8 : GL_RGBA16F; 0046 if (!m_texture || m_texture->size() != bufferSize || m_texture->internalFormat() != bufferFormat) { 0047 m_texture = GLTexture::allocate(bufferFormat, bufferSize); 0048 if (!m_texture) { 0049 return; 0050 } 0051 m_framebuffer = std::make_unique<GLFramebuffer>(m_texture.get()); 0052 } 0053 0054 RenderTarget offscreenRenderTarget(m_framebuffer.get(), renderTarget.colorDescription()); 0055 0056 RenderLayer renderLayer(layer()->loop()); 0057 renderLayer.setDelegate(std::make_unique<SceneDelegate>(Compositor::self()->cursorScene(), m_output)); 0058 renderLayer.delegate()->prePaint(); 0059 renderLayer.delegate()->paint(offscreenRenderTarget, infiniteRegion()); 0060 renderLayer.delegate()->postPaint(); 0061 0062 QMatrix4x4 mvp; 0063 mvp.scale(1, -1); // flip the y axis back 0064 mvp *= renderTarget.transform().toMatrix(); 0065 mvp.scale(1, -1); // undo ortho() flipping the y axis 0066 mvp.ortho(QRectF(QPointF(0, 0), m_output->transform().map(renderTarget.size()))); 0067 mvp.translate(cursorRect.x(), cursorRect.y()); 0068 0069 GLFramebuffer *fbo = renderTarget.framebuffer(); 0070 GLFramebuffer::pushFramebuffer(fbo); 0071 0072 const bool clipping = region != infiniteRegion(); 0073 const QRegion clipRegion = clipping ? RenderViewport(m_output->rectF(), m_output->scale(), renderTarget).mapToRenderTarget(dirty) : infiniteRegion(); 0074 0075 if (clipping) { 0076 glEnable(GL_SCISSOR_TEST); 0077 } 0078 0079 // Don't need to call GLVertexBuffer::beginFrame() and GLVertexBuffer::endOfFrame() because 0080 // the GLVertexBuffer::streamingBuffer() is not being used when painting cursor. 0081 glEnable(GL_BLEND); 0082 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 0083 0084 ShaderBinder binder(ShaderTrait::MapTexture); 0085 binder.shader()->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mvp); 0086 m_texture->render(clipRegion, cursorRect.size(), clipping); 0087 glDisable(GL_BLEND); 0088 0089 if (clipping) { 0090 glDisable(GL_SCISSOR_TEST); 0091 } 0092 0093 GLFramebuffer::popFramebuffer(); 0094 } 0095 0096 } // namespace KWin 0097 0098 #include "moc_cursordelegate_opengl.cpp"