kwin: adding proper clipping for transformed windows
This patch kind of reintroduces the old PaintClipper functionality. REVIEW: 104397
This commit is contained in:
parent
ba573c60ed
commit
05a8777edf
6 changed files with 74 additions and 54 deletions
|
@ -297,7 +297,7 @@ void GLTexture::unbind()
|
|||
d->unbind();
|
||||
}
|
||||
|
||||
void GLTexture::render(QRegion region, const QRect& rect)
|
||||
void GLTexture::render(QRegion region, const QRect& rect, bool hardwareClipping)
|
||||
{
|
||||
Q_D(GLTexture);
|
||||
if (rect.size() != d->m_cachedSize) {
|
||||
|
@ -338,7 +338,7 @@ void GLTexture::render(QRegion region, const QRect& rect)
|
|||
} else {
|
||||
pushMatrix(translation);
|
||||
}
|
||||
d->m_vbo->render(region, GL_TRIANGLE_STRIP);
|
||||
d->m_vbo->render(region, GL_TRIANGLE_STRIP, hardwareClipping);
|
||||
if (ShaderManager::instance()->isShaderBound()) {
|
||||
GLShader *shader = ShaderManager::instance()->getBoundShader();
|
||||
shader->setUniform(GLShader::WindowTransformation, QMatrix4x4());
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
virtual void discard();
|
||||
void bind();
|
||||
void unbind();
|
||||
void render(QRegion region, const QRect& rect);
|
||||
void render(QRegion region, const QRect& rect, bool hardwareClipping = false);
|
||||
|
||||
GLuint texture() const;
|
||||
GLenum target() const;
|
||||
|
|
|
@ -1145,18 +1145,17 @@ public:
|
|||
QColor color;
|
||||
|
||||
//! VBO is not supported
|
||||
void legacyPainting(QRegion region, GLenum primitiveMode);
|
||||
void legacyPainting(QRegion region, GLenum primitiveMode, bool hardwareClipping);
|
||||
//! VBO and shaders are both supported
|
||||
void corePainting(const QRegion& region, GLenum primitiveMode);
|
||||
void corePainting(const QRegion& region, GLenum primitiveMode, bool hardwareClipping);
|
||||
//! VBO is supported, but shaders are not supported
|
||||
void fallbackPainting(const QRegion& region, GLenum primitiveMode);
|
||||
void fallbackPainting(const QRegion& region, GLenum primitiveMode, bool hardwareClipping);
|
||||
};
|
||||
bool GLVertexBufferPrivate::supported = false;
|
||||
GLVertexBuffer *GLVertexBufferPrivate::streamingBuffer = NULL;
|
||||
|
||||
void GLVertexBufferPrivate::legacyPainting(QRegion region, GLenum primitiveMode)
|
||||
void GLVertexBufferPrivate::legacyPainting(QRegion region, GLenum primitiveMode, bool hardwareClipping)
|
||||
{
|
||||
Q_UNUSED(region)
|
||||
#ifdef KWIN_HAVE_OPENGLES
|
||||
Q_UNUSED(primitiveMode)
|
||||
#else
|
||||
|
@ -1172,7 +1171,14 @@ void GLVertexBufferPrivate::legacyPainting(QRegion region, GLenum primitiveMode)
|
|||
glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF());
|
||||
}
|
||||
|
||||
glDrawArrays(primitiveMode, 0, numberVertices);
|
||||
if (!hardwareClipping) {
|
||||
glDrawArrays(primitiveMode, 0, numberVertices);
|
||||
} else {
|
||||
foreach (const QRect& r, region.rects()) {
|
||||
glScissor(r.x(), displayHeight() - r.y() - r.height(), r.width(), r.height());
|
||||
glDrawArrays(primitiveMode, 0, numberVertices);
|
||||
}
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
if (!legacyTexCoords.isEmpty()) {
|
||||
|
@ -1181,9 +1187,8 @@ void GLVertexBufferPrivate::legacyPainting(QRegion region, GLenum primitiveMode)
|
|||
#endif
|
||||
}
|
||||
|
||||
void GLVertexBufferPrivate::corePainting(const QRegion& region, GLenum primitiveMode)
|
||||
void GLVertexBufferPrivate::corePainting(const QRegion& region, GLenum primitiveMode, bool hardwareClipping)
|
||||
{
|
||||
Q_UNUSED(region)
|
||||
GLShader *shader = ShaderManager::instance()->getBoundShader();
|
||||
GLint vertexAttrib = shader->attributeLocation("vertex");
|
||||
GLint texAttrib = shader->attributeLocation("texCoord");
|
||||
|
@ -1205,7 +1210,14 @@ void GLVertexBufferPrivate::corePainting(const QRegion& region, GLenum primitive
|
|||
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
}
|
||||
|
||||
glDrawArrays(primitiveMode, 0, numberVertices);
|
||||
if (!hardwareClipping) {
|
||||
glDrawArrays(primitiveMode, 0, numberVertices);
|
||||
} else {
|
||||
foreach (const QRect& r, region.rects()) {
|
||||
glScissor(r.x(), displayHeight() - r.y() - r.height(), r.width(), r.height());
|
||||
glDrawArrays(primitiveMode, 0, numberVertices);
|
||||
}
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
|
@ -1215,9 +1227,8 @@ void GLVertexBufferPrivate::corePainting(const QRegion& region, GLenum primitive
|
|||
glDisableVertexAttribArray(vertexAttrib);
|
||||
}
|
||||
|
||||
void GLVertexBufferPrivate::fallbackPainting(const QRegion& region, GLenum primitiveMode)
|
||||
void GLVertexBufferPrivate::fallbackPainting(const QRegion& region, GLenum primitiveMode, bool hardwareClipping)
|
||||
{
|
||||
Q_UNUSED(region)
|
||||
#ifdef KWIN_HAVE_OPENGLES
|
||||
Q_UNUSED(primitiveMode)
|
||||
#else
|
||||
|
@ -1234,7 +1245,14 @@ void GLVertexBufferPrivate::fallbackPainting(const QRegion& region, GLenum primi
|
|||
}
|
||||
|
||||
// Clip using scissoring
|
||||
glDrawArrays(primitiveMode, 0, numberVertices);
|
||||
if (!hardwareClipping) {
|
||||
glDrawArrays(primitiveMode, 0, numberVertices);
|
||||
} else {
|
||||
foreach (const QRect& r, region.rects()) {
|
||||
glScissor(r.x(), displayHeight() - r.y() - r.height(), r.width(), r.height());
|
||||
glDrawArrays(primitiveMode, 0, numberVertices);
|
||||
}
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
|
@ -1306,17 +1324,17 @@ void GLVertexBuffer::setData(int numberVertices, int dim, const float* vertices,
|
|||
|
||||
void GLVertexBuffer::render(GLenum primitiveMode)
|
||||
{
|
||||
render(infiniteRegion(), primitiveMode);
|
||||
render(infiniteRegion(), primitiveMode, false);
|
||||
}
|
||||
|
||||
void GLVertexBuffer::render(const QRegion& region, GLenum primitiveMode)
|
||||
void GLVertexBuffer::render(const QRegion& region, GLenum primitiveMode, bool hardwareClipping)
|
||||
{
|
||||
if (!GLVertexBufferPrivate::supported) {
|
||||
d->legacyPainting(region, primitiveMode);
|
||||
d->legacyPainting(region, primitiveMode, hardwareClipping);
|
||||
} else if (ShaderManager::instance()->isShaderBound()) {
|
||||
d->corePainting(region, primitiveMode);
|
||||
d->corePainting(region, primitiveMode, hardwareClipping);
|
||||
} else {
|
||||
d->fallbackPainting(region, primitiveMode);
|
||||
d->fallbackPainting(region, primitiveMode, hardwareClipping);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -510,9 +510,10 @@ public:
|
|||
*/
|
||||
void render(GLenum primitiveMode);
|
||||
/**
|
||||
* Same as above restricting painting to @a region.
|
||||
* Same as above restricting painting to @a region if @a hardwareClipping is true.
|
||||
* It's within the caller's responsibility to enable GL_SCISSOR_TEST.
|
||||
*/
|
||||
void render(const QRegion& region, GLenum primitiveMode);
|
||||
void render(const QRegion& region, GLenum primitiveMode, bool hardwareClipping = false);
|
||||
/**
|
||||
* Sets the color the geometry will be rendered with.
|
||||
* For legacy rendering glColor is used before rendering the geometry.
|
||||
|
|
|
@ -445,22 +445,11 @@ QMatrix4x4 SceneOpenGL::Window::transformation(int mask, const WindowPaintData &
|
|||
// paint the window
|
||||
void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData data)
|
||||
{
|
||||
// check if there is something to paint (e.g. don't paint if the window
|
||||
// is only opaque and only PAINT_WINDOW_TRANSLUCENT is requested)
|
||||
/* HACK: It seems this causes painting glitches, disable temporarily
|
||||
bool opaque = isOpaque() && data.opacity == 1.0;
|
||||
if (( mask & PAINT_WINDOW_OPAQUE ) ^ ( mask & PAINT_WINDOW_TRANSLUCENT ))
|
||||
{ // We are only painting either opaque OR translucent windows, not both
|
||||
if ( mask & PAINT_WINDOW_OPAQUE && !opaque )
|
||||
return; // Only painting opaque and window is translucent
|
||||
if ( mask & PAINT_WINDOW_TRANSLUCENT && opaque )
|
||||
return; // Only painting translucent and window is opaque
|
||||
}*/
|
||||
|
||||
if (region.isEmpty())
|
||||
return;
|
||||
|
||||
if (region != infiniteRegion() && !(mask & PAINT_WINDOW_TRANSFORMED)) {
|
||||
bool hardwareClipping = region != infiniteRegion() && (mask & PAINT_WINDOW_TRANSFORMED);
|
||||
if (region != infiniteRegion() && !hardwareClipping) {
|
||||
WindowQuadList quads;
|
||||
const QRegion filterRegion = region.translated(-x(), -y());
|
||||
// split all quads in bounding rect with the actual rects in the region
|
||||
|
@ -483,8 +472,13 @@ void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData
|
|||
data.quads = quads;
|
||||
}
|
||||
|
||||
if (!bindTexture())
|
||||
if (!bindTexture()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hardwareClipping) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
// Update the texture filter
|
||||
if (options->glSmoothScale() != 0 &&
|
||||
|
@ -523,7 +517,7 @@ void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData
|
|||
|
||||
// shadow
|
||||
if (m_shadow) {
|
||||
paintShadow(region, data);
|
||||
paintShadow(region, data, hardwareClipping);
|
||||
}
|
||||
// decorations
|
||||
Client *client = dynamic_cast<Client*>(toplevel);
|
||||
|
@ -578,10 +572,10 @@ void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData
|
|||
}
|
||||
}
|
||||
|
||||
paintDecoration(top, DecorationTop, region, topRect, data, topList, updateDeco);
|
||||
paintDecoration(left, DecorationLeft, region, leftRect, data, leftList, updateDeco);
|
||||
paintDecoration(right, DecorationRight, region, rightRect, data, rightList, updateDeco);
|
||||
paintDecoration(bottom, DecorationBottom, region, bottomRect, data, bottomList, updateDeco);
|
||||
paintDecoration(top, DecorationTop, region, topRect, data, topList, updateDeco, hardwareClipping);
|
||||
paintDecoration(left, DecorationLeft, region, leftRect, data, leftList, updateDeco, hardwareClipping);
|
||||
paintDecoration(right, DecorationRight, region, rightRect, data, rightList, updateDeco, hardwareClipping);
|
||||
paintDecoration(bottom, DecorationBottom, region, bottomRect, data, bottomList, updateDeco, hardwareClipping);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -590,18 +584,22 @@ void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData
|
|||
if (!contentQuads.empty()) {
|
||||
texture.bind();
|
||||
prepareStates(Content, data.opacity * data.contents_opacity, data.brightness, data.saturation, data.shader);
|
||||
renderQuads(mask, region, contentQuads, &texture);
|
||||
renderQuads(mask, region, contentQuads, &texture, false, hardwareClipping);
|
||||
restoreStates(Content, data.opacity * data.contents_opacity, data.brightness, data.saturation, data.shader);
|
||||
texture.unbind();
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
if (static_cast<SceneOpenGL*>(scene)->debug) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
renderQuads(mask, region, contentQuads, &texture);
|
||||
renderQuads(mask, region, contentQuads, &texture, false, hardwareClipping);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (hardwareClipping) {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
if (sceneShader) {
|
||||
ShaderManager::instance()->popShader();
|
||||
data.shader = NULL;
|
||||
|
@ -610,7 +608,9 @@ void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData
|
|||
}
|
||||
}
|
||||
|
||||
void SceneOpenGL::Window::paintDecoration(const QPixmap* decoration, TextureType decorationType, const QRegion& region, const QRect& rect, const WindowPaintData& data, const WindowQuadList& quads, bool updateDeco)
|
||||
void SceneOpenGL::Window::paintDecoration(const QPixmap* decoration, TextureType decorationType,
|
||||
const QRegion& region, const QRect& rect, const WindowPaintData& data,
|
||||
const WindowQuadList& quads, bool updateDeco, bool hardwareClipping)
|
||||
{
|
||||
SceneOpenGL::Texture* decorationTexture;
|
||||
switch(decorationType) {
|
||||
|
@ -658,19 +658,19 @@ void SceneOpenGL::Window::paintDecoration(const QPixmap* decoration, TextureType
|
|||
|
||||
prepareStates(decorationType, data.opacity * data.decoration_opacity, data.brightness, data.saturation, data.shader);
|
||||
makeDecorationArrays(quads, rect, decorationTexture);
|
||||
GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES);
|
||||
GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES, hardwareClipping);
|
||||
restoreStates(decorationType, data.opacity * data.decoration_opacity, data.brightness, data.saturation, data.shader);
|
||||
decorationTexture->unbind();
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
if (static_cast<SceneOpenGL*>(scene)->debug) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES);
|
||||
GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES, hardwareClipping);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SceneOpenGL::Window::paintShadow(const QRegion ®ion, const WindowPaintData &data)
|
||||
void SceneOpenGL::Window::paintShadow(const QRegion ®ion, const WindowPaintData &data, bool hardwareClipping)
|
||||
{
|
||||
WindowQuadList quads = data.quads.select(WindowQuadShadowTopLeft);
|
||||
quads.append(data.quads.select(WindowQuadShadowTop));
|
||||
|
@ -694,13 +694,13 @@ void SceneOpenGL::Window::paintShadow(const QRegion ®ion, const WindowPaintDa
|
|||
texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
texture->bind();
|
||||
prepareStates(Shadow, data.opacity, data.brightness, data.saturation, data.shader, texture);
|
||||
renderQuads(0, region, quads, texture, true);
|
||||
renderQuads(0, region, quads, texture, true, hardwareClipping);
|
||||
restoreStates(Shadow, data.opacity, data.brightness, data.saturation, data.shader, texture);
|
||||
texture->unbind();
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
if (static_cast<SceneOpenGL*>(scene)->debug) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
renderQuads(0, region, quads, texture);
|
||||
renderQuads(0, region, quads, texture, true, hardwareClipping);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
#endif
|
||||
|
@ -765,7 +765,8 @@ void SceneOpenGL::Window::makeDecorationArrays(const WindowQuadList& quads, cons
|
|||
GLVertexBuffer::streamingBuffer()->setData(quads.count() * 6, 2, vertices.data(), texcoords.data());
|
||||
}
|
||||
|
||||
void SceneOpenGL::Window::renderQuads(int, const QRegion& region, const WindowQuadList& quads, GLTexture *tex, bool normalized)
|
||||
void SceneOpenGL::Window::renderQuads(int, const QRegion& region, const WindowQuadList& quads,
|
||||
GLTexture *tex, bool normalized, bool hardwareClipping)
|
||||
{
|
||||
if (quads.isEmpty())
|
||||
return;
|
||||
|
@ -785,7 +786,7 @@ void SceneOpenGL::Window::renderQuads(int, const QRegion& region, const WindowQu
|
|||
#endif
|
||||
quads.makeArrays(&vertices, &texcoords, size, tex->isYInverted());
|
||||
GLVertexBuffer::streamingBuffer()->setData(quads.count() * 6, 2, vertices, texcoords);
|
||||
GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES);
|
||||
GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES, hardwareClipping);
|
||||
delete[] vertices;
|
||||
delete[] texcoords;
|
||||
}
|
||||
|
|
|
@ -175,10 +175,10 @@ protected:
|
|||
};
|
||||
|
||||
QMatrix4x4 transformation(int mask, const WindowPaintData &data) const;
|
||||
void paintDecoration(const QPixmap* decoration, TextureType decorationType, const QRegion& region, const QRect& rect, const WindowPaintData& data, const WindowQuadList& quads, bool updateDeco);
|
||||
void paintShadow(const QRegion ®ion, const WindowPaintData &data);
|
||||
void paintDecoration(const QPixmap* decoration, TextureType decorationType, const QRegion& region, const QRect& rect, const WindowPaintData& data, const WindowQuadList& quads, bool updateDeco, bool hardwareClipping);
|
||||
void paintShadow(const QRegion ®ion, const WindowPaintData &data, bool hardwareClipping);
|
||||
void makeDecorationArrays(const WindowQuadList& quads, const QRect &rect, Texture *tex) const;
|
||||
void renderQuads(int, const QRegion& region, const WindowQuadList& quads, GLTexture* tex, bool normalized = false);
|
||||
void renderQuads(int, const QRegion& region, const WindowQuadList& quads, GLTexture* tex, bool normalized, bool hardwareClipping);
|
||||
void prepareStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader);
|
||||
void prepareStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader, GLTexture *texture);
|
||||
void prepareRenderStates(TextureType type, double opacity, double brightness, double saturation, GLTexture *tex);
|
||||
|
|
Loading…
Reference in a new issue