2021-06-22 00:23:17 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
|
|
|
|
|
|
|
SPDX-FileCopyrightText: 2021 Xaver Hugl <xaver.hugl@gmail.com>
|
|
|
|
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
|
|
|
#include "shadowbuffer.h"
|
|
|
|
|
|
|
|
#include "logging.h"
|
|
|
|
#include "drm_output.h"
|
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
|
|
|
static const float vertices[] = {
|
|
|
|
-1.0f, 1.0f,
|
|
|
|
-1.0f, -1.0f,
|
|
|
|
1.0f, -1.0f,
|
|
|
|
|
|
|
|
-1.0f, 1.0f,
|
|
|
|
1.0f, -1.0f,
|
|
|
|
1.0f, 1.0f,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const float texCoords[] = {
|
|
|
|
0.0f, 1.0f,
|
|
|
|
0.0f, 0.0f,
|
|
|
|
1.0f, 0.0f,
|
|
|
|
|
|
|
|
0.0f, 1.0f,
|
|
|
|
1.0f, 0.0f,
|
|
|
|
1.0f, 1.0f
|
|
|
|
};
|
|
|
|
|
2021-11-10 13:47:13 +00:00
|
|
|
ShadowBuffer::ShadowBuffer(const QSize &size, const GbmFormat &format)
|
2021-05-25 22:05:17 +00:00
|
|
|
: m_size(size)
|
2021-06-22 00:23:17 +00:00
|
|
|
{
|
|
|
|
glGenFramebuffers(1, &m_framebuffer);
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
|
|
|
|
GLRenderTarget::setKWinFramebuffer(m_framebuffer);
|
|
|
|
|
|
|
|
glGenTextures(1, &m_texture);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, m_texture);
|
2021-11-10 13:47:13 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat(format), size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2021-06-22 00:23:17 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
|
|
|
|
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
|
|
|
qCCritical(KWIN_DRM) << "Error: framebuffer not complete!";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
GLRenderTarget::setKWinFramebuffer(0);
|
|
|
|
|
|
|
|
m_vbo.reset(new GLVertexBuffer(KWin::GLVertexBuffer::Static));
|
|
|
|
m_vbo->setData(6, 2, vertices, texCoords);
|
|
|
|
}
|
|
|
|
|
|
|
|
ShadowBuffer::~ShadowBuffer()
|
|
|
|
{
|
|
|
|
glDeleteTextures(1, &m_texture);
|
|
|
|
glDeleteFramebuffers(1, &m_framebuffer);
|
|
|
|
}
|
|
|
|
|
2021-07-26 23:11:50 +00:00
|
|
|
void ShadowBuffer::render(DrmAbstractOutput *output)
|
2021-06-22 00:23:17 +00:00
|
|
|
{
|
|
|
|
const auto size = output->modeSize();
|
|
|
|
glViewport(0, 0, size.width(), size.height());
|
|
|
|
auto shader = ShaderManager::instance()->pushShader(ShaderTrait::MapTexture);
|
|
|
|
|
|
|
|
QMatrix4x4 mvpMatrix;
|
|
|
|
|
|
|
|
switch (output->transform()) {
|
|
|
|
case DrmOutput::Transform::Normal:
|
|
|
|
case DrmOutput::Transform::Flipped:
|
|
|
|
break;
|
|
|
|
case DrmOutput::Transform::Rotated90:
|
|
|
|
case DrmOutput::Transform::Flipped90:
|
|
|
|
mvpMatrix.rotate(90, 0, 0, 1);
|
|
|
|
break;
|
|
|
|
case DrmOutput::Transform::Rotated180:
|
|
|
|
case DrmOutput::Transform::Flipped180:
|
|
|
|
mvpMatrix.rotate(180, 0, 0, 1);
|
|
|
|
break;
|
|
|
|
case DrmOutput::Transform::Rotated270:
|
|
|
|
case DrmOutput::Transform::Flipped270:
|
|
|
|
mvpMatrix.rotate(270, 0, 0, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (output->transform()) {
|
|
|
|
case DrmOutput::Transform::Flipped:
|
|
|
|
case DrmOutput::Transform::Flipped90:
|
|
|
|
case DrmOutput::Transform::Flipped180:
|
|
|
|
case DrmOutput::Transform::Flipped270:
|
|
|
|
mvpMatrix.scale(-1, 1);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
shader->setUniform(GLShader::ModelViewProjectionMatrix, mvpMatrix);
|
|
|
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
GLRenderTarget::setKWinFramebuffer(0);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, m_texture);
|
|
|
|
m_vbo->render(GL_TRIANGLES);
|
|
|
|
ShaderManager::instance()->popShader();
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ShadowBuffer::bind()
|
|
|
|
{
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
|
|
|
|
GLRenderTarget::setKWinFramebuffer(m_framebuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShadowBuffer::isComplete() const
|
|
|
|
{
|
|
|
|
return m_texture && m_framebuffer && m_vbo;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ShadowBuffer::texture() const
|
|
|
|
{
|
|
|
|
return m_texture;
|
|
|
|
}
|
|
|
|
|
2021-05-25 22:05:17 +00:00
|
|
|
QSize ShadowBuffer::textureSize() const
|
|
|
|
{
|
|
|
|
return m_size;
|
|
|
|
}
|
|
|
|
|
2021-11-10 13:47:13 +00:00
|
|
|
GLint ShadowBuffer::internalFormat(const GbmFormat &format)
|
|
|
|
{
|
|
|
|
if (format.redSize <= 8 && format.greenSize <= 8 && format.blueSize <= 8) {
|
|
|
|
return GL_RGBA8;
|
|
|
|
} else if (format.redSize <= 10 && format.greenSize <= 10 && format.blueSize <= 10) {
|
|
|
|
return GL_RGB10_A2;
|
|
|
|
} else if (format.redSize <= 12 && format.greenSize <= 12 && format.blueSize <= 12) {
|
|
|
|
return GL_RGBA12;
|
|
|
|
} else {
|
|
|
|
return GL_RGBA16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-22 00:23:17 +00:00
|
|
|
}
|