Skip to content

Commit

Permalink
blur/fake-blur: transform colorspace
Browse files Browse the repository at this point in the history
  • Loading branch information
taj-ny committed Sep 17, 2024
1 parent acde198 commit 3884d5d
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 15 deletions.
52 changes: 39 additions & 13 deletions src/blur.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <KSharedConfig>

#include <KDecoration2/Decoration>
#include <utility>

Q_LOGGING_CATEGORY(KWIN_BLUR, "kwin_better_blur", QtWarningMsg)

Expand Down Expand Up @@ -617,12 +618,17 @@ void BlurEffect::drawWindow(const RenderTarget &renderTarget, const RenderViewpo
effects->drawWindow(renderTarget, viewport, w, mask, region, data);
}

GLTexture *BlurEffect::ensureFakeBlurTexture(const Output *output)
GLTexture *BlurEffect::ensureFakeBlurTexture(const Output *output, const RenderTarget &renderTarget)
{
if (m_fakeBlurTextures.contains(output)) {
return m_fakeBlurTextures[output];
}

GLenum textureFormat = GL_RGBA8;
if (renderTarget.texture()) {
textureFormat = renderTarget.texture()->internalFormat();
}

QImage image;
if (m_settings.fakeBlur.imageSource == FakeBlurImageSource::DesktopWallpaper) {
EffectWindow *desktop;
Expand All @@ -636,7 +642,7 @@ GLTexture *BlurEffect::ensureFakeBlurTexture(const Output *output)
return nullptr;
}

std::unique_ptr<GLTexture> desktopTexture = GLTexture::allocate(GL_RGBA8, desktop->size().toSize());
std::unique_ptr<GLTexture> desktopTexture = GLTexture::allocate(textureFormat, desktop->size().toSize());
desktopTexture->setFilter(GL_LINEAR);
desktopTexture->setWrapMode(GL_CLAMP_TO_EDGE);
if (!desktopTexture) {
Expand Down Expand Up @@ -679,9 +685,29 @@ GLTexture *BlurEffect::ensureFakeBlurTexture(const Output *output)
return nullptr;
}

std::unique_ptr<GLTexture> imageTexture = GLTexture::upload(image);

// Transform image colorspace
std::unique_ptr<GLTexture> imageTransformedColorspaceTexture = GLTexture::allocate(textureFormat, image.size());
std::unique_ptr<GLFramebuffer> imageTransformedColorspaceFramebuffer = std::make_unique<GLFramebuffer>(imageTransformedColorspaceTexture.get());

GLShader *shader = ShaderManager::instance()->pushShader(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace);
shader->setColorspaceUniforms(ColorDescription::sRGB, renderTarget.colorDescription());
QMatrix4x4 projectionMatrix;
projectionMatrix.scale(1, -1);
projectionMatrix.ortho(QRect(0, 0, image.width(), image.height()));
shader->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, projectionMatrix);
GLFramebuffer::pushFramebuffer(imageTransformedColorspaceFramebuffer.get());

imageTexture->render(image.size());
imageTexture = std::move(imageTransformedColorspaceTexture);

GLFramebuffer::popFramebuffer();
ShaderManager::instance()->popShader();

return m_fakeBlurTextures[output] = (m_settings.fakeBlur.blurCustomImage
? blur(image)
: GLTexture::upload(image).release());
? blur(std::move(imageTexture))
: imageTexture.release());
}

GLTexture *BlurEffect::ensureNoiseTexture()
Expand Down Expand Up @@ -819,7 +845,7 @@ void BlurEffect::blur(BlurRenderData &renderInfo, const RenderTarget &renderTarg
// reset.
GLTexture *fakeBlurTexture = nullptr;
if (w && hasFakeBlur(w)) {
fakeBlurTexture = ensureFakeBlurTexture(m_currentScreen);
fakeBlurTexture = ensureFakeBlurTexture(m_currentScreen, renderTarget);
}

// Fetch the pixels behind the shape that is going to be blurred.
Expand Down Expand Up @@ -1057,21 +1083,21 @@ void BlurEffect::blur(BlurRenderData &renderInfo, const RenderTarget &renderTarg
vbo->unbindArrays();
}

GLTexture *BlurEffect::blur(const QImage &image)
GLTexture *BlurEffect::blur(std::unique_ptr<GLTexture> texture)
{
auto imageTexture = GLTexture::upload(image);
auto imageFramebuffer = std::make_unique<GLFramebuffer>(imageTexture.get());
const QRect textureRect = QRect(0, 0, texture->width(), texture->height());
auto blurredFramebuffer = std::make_unique<GLFramebuffer>(texture.get());

BlurRenderData renderData;
const RenderTarget renderTarget(imageFramebuffer.get());
const RenderViewport renderViewport(image.rect(), 1.0, renderTarget);
const RenderTarget renderTarget(blurredFramebuffer.get());
const RenderViewport renderViewport(textureRect, 1.0, renderTarget);
WindowPaintData data;

GLFramebuffer::pushFramebuffer(imageFramebuffer.get());
blur(renderData, renderTarget, renderViewport, nullptr, 0, image.rect(), data);
GLFramebuffer::pushFramebuffer(blurredFramebuffer.get());
blur(renderData, renderTarget, renderViewport, nullptr, 0, textureRect, data);
GLFramebuffer::popFramebuffer();

return imageTexture.release();
return texture.release();
}

bool BlurEffect::isActive() const
Expand Down
4 changes: 2 additions & 2 deletions src/blur.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ public Q_SLOTS:
* @param w The pointer to the window being blurred, nullptr if an image is being blurred.
*/
void blur(BlurRenderData &renderInfo, const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion &region, WindowPaintData &data);
GLTexture *blur(const QImage &image);
GLTexture *blur(std::unique_ptr<GLTexture> texture);

GLTexture *ensureFakeBlurTexture(const Output *output);
GLTexture *ensureFakeBlurTexture(const Output *output, const RenderTarget &renderTarget);
GLTexture *ensureNoiseTexture();
private:
struct
Expand Down

0 comments on commit 3884d5d

Please sign in to comment.