File indexing completed on 2025-04-20 10:57:36

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2021 Xaver Hugl <xaver.hugl@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "drm_shadow_buffer.h"
0010 
0011 #include "drm_logging.h"
0012 #include "drm_output.h"
0013 
0014 namespace KWin
0015 {
0016 
0017 static const float vertices[] = {
0018     -1.0f,
0019     1.0f,
0020     -1.0f,
0021     -1.0f,
0022     1.0f,
0023     -1.0f,
0024 
0025     -1.0f,
0026     1.0f,
0027     1.0f,
0028     -1.0f,
0029     1.0f,
0030     1.0f,
0031 };
0032 
0033 static const float texCoords[] = {
0034     0.0f, 1.0f,
0035     0.0f, 0.0f,
0036     1.0f, 0.0f,
0037 
0038     0.0f, 1.0f,
0039     1.0f, 0.0f,
0040     1.0f, 1.0f};
0041 
0042 ShadowBuffer::ShadowBuffer(const QSize &size, const GbmFormat &format)
0043     : m_size(size)
0044     , m_drmFormat(format.drmFormat)
0045 {
0046     m_texture = std::make_unique<GLTexture>(internalFormat(format), size);
0047     m_texture->setFilter(GL_NEAREST);
0048     m_texture->setYInverted(true);
0049 
0050     m_fbo = std::make_unique<GLFramebuffer>(m_texture.get());
0051     if (!m_fbo->valid()) {
0052         qCCritical(KWIN_DRM) << "Error: framebuffer not complete!";
0053         return;
0054     }
0055 
0056     m_vbo = std::make_unique<GLVertexBuffer>(KWin::GLVertexBuffer::Static);
0057     m_vbo->setData(6, 2, vertices, texCoords);
0058 }
0059 
0060 ShadowBuffer::~ShadowBuffer()
0061 {
0062 }
0063 
0064 void ShadowBuffer::render(DrmPlane::Transformations transform)
0065 {
0066     QMatrix4x4 mvpMatrix;
0067     if (transform & DrmPlane::Transformation::Rotate90) {
0068         mvpMatrix.rotate(90, 0, 0, 1);
0069     } else if (transform & DrmPlane::Transformation::Rotate180) {
0070         mvpMatrix.rotate(180, 0, 0, 1);
0071     } else if (transform & DrmPlane::Transformation::Rotate270) {
0072         mvpMatrix.rotate(270, 0, 0, 1);
0073     }
0074     if (transform & DrmPlane::Transformation::ReflectX) {
0075         mvpMatrix.scale(-1, 1);
0076     }
0077     if (transform & DrmPlane::Transformation::ReflectY) {
0078         mvpMatrix.scale(1, -1);
0079     }
0080 
0081     auto shader = ShaderManager::instance()->pushShader(ShaderTrait::MapTexture);
0082     shader->setUniform(GLShader::ModelViewProjectionMatrix, mvpMatrix);
0083 
0084     m_texture->bind();
0085     m_vbo->render(GL_TRIANGLES);
0086     ShaderManager::instance()->popShader();
0087 }
0088 
0089 GLFramebuffer *ShadowBuffer::fbo() const
0090 {
0091     return m_fbo.get();
0092 }
0093 
0094 std::shared_ptr<GLTexture> ShadowBuffer::texture() const
0095 {
0096     return m_texture;
0097 }
0098 
0099 bool ShadowBuffer::isComplete() const
0100 {
0101     return m_fbo->valid() && m_vbo;
0102 }
0103 
0104 uint32_t ShadowBuffer::drmFormat() const
0105 {
0106     return m_drmFormat;
0107 }
0108 
0109 GLint ShadowBuffer::internalFormat(const GbmFormat &format) const
0110 {
0111     if (format.bpp <= 24) {
0112         return GL_RGBA8;
0113     } else if (format.bpp <= 30) {
0114         return GL_RGB10_A2;
0115     } else {
0116         return GL_RGBA16;
0117     }
0118 }
0119 
0120 }