diff --git a/libkwineffects/kwinglutils.h b/libkwineffects/kwinglutils.h --- a/libkwineffects/kwinglutils.h +++ b/libkwineffects/kwinglutils.h @@ -129,6 +129,7 @@ enum Vec4Uniform { ModulationConstant, + TextureClamp, Vec4UniformCount }; @@ -186,6 +187,7 @@ UniformColor = (1 << 1), Modulate = (1 << 2), AdjustSaturation = (1 << 3), + ClampTexture = (1 << 4), }; Q_DECLARE_FLAGS(ShaderTraits, ShaderTrait) diff --git a/libkwineffects/kwinglutils.cpp b/libkwineffects/kwinglutils.cpp --- a/libkwineffects/kwinglutils.cpp +++ b/libkwineffects/kwinglutils.cpp @@ -347,6 +347,7 @@ mFloatLocation[Saturation] = uniformLocation("saturation"); mColorLocation[Color] = uniformLocation("geometryColor"); + mVec4Location[TextureClamp] = uniformLocation("textureClamp"); mLocationsResolved = true; } @@ -877,22 +878,32 @@ } else if (traits & ShaderTrait::UniformColor) stream << "uniform vec4 geometryColor;\n"; + if (traits & ShaderTrait::ClampTexture) { + stream << "uniform vec4 textureClamp;\n"; + } + if (output != QByteArrayLiteral("gl_FragColor")) stream << "\nout vec4 " << output << ";\n"; stream << "\nvoid main(void)\n{\n"; if (traits & ShaderTrait::MapTexture) { - if (traits & (ShaderTrait::Modulate | ShaderTrait::AdjustSaturation)) { - stream << " vec4 texel = " << textureLookup << "(sampler, texcoord0);\n"; + stream << "vec2 texcoordC = texcoord0;\n"; + if (traits & ShaderTrait::ClampTexture) { + stream << "texcoordC.x = clamp(texcoordC.x, textureClamp.x, textureClamp.z);\n"; + stream << "texcoordC.y = clamp(texcoordC.y, textureClamp.y, textureClamp.w);\n"; + } + + if (traits & (ShaderTrait::Modulate | ShaderTrait::AdjustSaturation)) { + stream << " vec4 texel = " << textureLookup << "(sampler, texcoordC);\n"; if (traits & ShaderTrait::Modulate) stream << " texel *= modulation;\n"; if (traits & ShaderTrait::AdjustSaturation) stream << " texel.rgb = mix(vec3(dot(texel.rgb, vec3(0.2126, 0.7152, 0.0722))), texel.rgb, saturation);\n"; stream << " " << output << " = texel;\n"; } else { - stream << " " << output << " = " << textureLookup << "(sampler, texcoord0);\n"; + stream << " " << output << " = " << textureLookup << "(sampler, texcoordC);\n"; } } else if (traits & ShaderTrait::UniformColor) stream << " " << output << " = geometryColor;\n"; diff --git a/plugins/scenes/opengl/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp --- a/plugins/scenes/opengl/scene_opengl.cpp +++ b/plugins/scenes/opengl/scene_opengl.cpp @@ -1381,9 +1381,16 @@ const QMatrix4x4 modelViewProjection = modelViewProjectionMatrix(mask, data); const QMatrix4x4 mvpMatrix = modelViewProjection * windowMatrix; + + bool useX11TextureClamp = false; + GLShader *shader = data.shader; if (!shader) { ShaderTraits traits = ShaderTrait::MapTexture; + if (kwinApp()->operationMode() == Application::OperationModeX11) { + useX11TextureClamp = true; + traits |= ShaderTrait::ClampTexture; + }; if (data.opacity() != 1.0 || data.brightness() != 1.0 || data.crossFadeProgress() != 1.0) traits |= ShaderTrait::Modulate; @@ -1506,6 +1513,25 @@ nodes[i].texture->setWrapMode(GL_CLAMP_TO_EDGE); nodes[i].texture->bind(); + if (i == ContentLeaf && useX11TextureClamp) { + // X11 windows are reparented to have their buffer in the middle of a larger texture + // holding the frame window. + // This code passes the texture geometry to the fragment shader + // any samples near the edge of the texture will be constrained to be + // at least half a pixel in bounds, meaning we don't bleed the transparent border + QRectF bufferContentRect = clientShape().boundingRect(); + bufferContentRect.adjust(0.5, 0.5, -0.5, -0.5); + const QRect bufferGeometry = toplevel->bufferGeometry(); + + float leftClamp = bufferContentRect.left() / bufferGeometry.width(); + float topClamp = bufferContentRect.top() / bufferGeometry.height(); + float rightClamp = bufferContentRect.right() / bufferGeometry.width(); + float bottomClamp = bufferContentRect.bottom() / bufferGeometry.height(); + shader->setUniform(GLShader::TextureClamp, QVector4D({leftClamp, topClamp, rightClamp, bottomClamp})); + } else { + shader->setUniform(GLShader::TextureClamp, QVector4D({0, 0, 1, 1})); + } + vbo->draw(region, primitiveType, nodes[i].firstVertex, nodes[i].vertexCount, m_hardwareClipping); }