1
/********************************************************************
2
KWin - the KDE window manager
3
This file is part of the KDE project.
5
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
6
Copyright (C) 2009, 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
8
Based on glcompmgr code by Felix Bellaby.
9
Using code from Compiz and Beryl.
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 2 of the License, or
14
(at your option) any later version.
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
21
You should have received a copy of the GNU General Public License
22
along with this program. If not, see <http://www.gnu.org/licenses/>.
23
*********************************************************************/
27
This is the OpenGL-based compositing code. It is the primary and most powerful
30
Sources and other compositing managers:
31
=======================================
35
- OpenGL Redbook (http://opengl.org/documentation/red_book/ - note it's only version 1.1)
36
- GLX docs (http://opengl.org/documentation/specs/glx/glx1.4.pdf)
37
- extensions docs (http://www.opengl.org/registry/)
40
- http://lists.freedesktop.org/archives/xorg/2006-July/017006.html ,
41
- http://www.mail-archive.com/compiz%40lists.freedesktop.org/msg00023.html
42
- simple and easy to understand
43
- works even without texture_from_pixmap extension
44
- claims to support several different gfx cards
45
- compile with something like
46
"gcc -Wall glcompmgr-0.5.c `pkg-config --cflags --libs glib-2.0` -lGL -lXcomposite -lXdamage -L/usr/X11R6/lib"
49
- git clone git://anongit.freedesktop.org/git/xorg/app/compiz
50
- the ultimate <whatever>
52
- git clone git://anongit.freedesktop.org/git/xorg/app/glxcompgr
53
- a rather old version of compiz, but also simpler and as such simpler
58
- http://beryl-project.org
59
- git clone git://anongit.beryl-project.org/beryl/beryl-core (or beryl-plugins etc. ,
60
the full list should be at git://anongit.beryl-project.org/beryl/)
63
- cvs -d :pserver:anonymous@anoncvs.gnome.org:/cvs/gnome co libcm
64
- not much idea about it, the model differs a lot from KWin/Compiz/Beryl
65
- does not seem to be very powerful or with that much development going on
69
#include "scene_opengl.h"
70
#include "kwinglplatform.h"
72
#include <kxerrorhandler.h>
74
#include <kwinglplatform.h>
83
// turns on checks for opengl errors in various places (for easier finding of them)
84
// normally only few of them are enabled
85
//#define CHECK_GL_ERROR
87
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
89
#include <X11/extensions/Xcomposite.h>
99
extern int currentRefreshRate();
101
//****************************************
103
//****************************************
105
bool SceneOpenGL::db; // destination drawable is double-buffered
107
#ifdef KWIN_HAVE_OPENGLES
108
#include "scene_opengl_egl.cpp"
110
#include "scene_opengl_glx.cpp"
113
bool SceneOpenGL::initFailed() const
118
bool SceneOpenGL::selectMode()
120
if (!initDrawableConfigs())
125
QMatrix4x4 SceneOpenGL::transformation(int mask, const ScreenPaintData &data) const
129
if (!(mask & PAINT_SCREEN_TRANSFORMED))
132
matrix.translate(data.xTranslate, data.yTranslate, data.zTranslate);
133
matrix.scale(data.xScale, data.yScale, data.zScale);
138
// Apply the rotation
139
const qreal xAxis = (data.rotation->axis == RotationData::XAxis ? 1.0 : 0.0);
140
const qreal yAxis = (data.rotation->axis == RotationData::YAxis ? 1.0 : 0.0);
141
const qreal zAxis = (data.rotation->axis == RotationData::ZAxis ? 1.0 : 0.0);
143
matrix.translate(data.rotation->xRotationPoint,
144
data.rotation->yRotationPoint,
145
data.rotation->zRotationPoint);
147
matrix.rotate(data.rotation->angle, xAxis, yAxis, zAxis);
149
matrix.translate(-data.rotation->xRotationPoint,
150
-data.rotation->yRotationPoint,
151
-data.rotation->zRotationPoint);
156
void SceneOpenGL::paintGenericScreen(int mask, ScreenPaintData data)
158
ShaderManager *shaderManager = ShaderManager::instance();
159
const bool useShader = shaderManager->isValid();
160
const QMatrix4x4 matrix = transformation(mask, data);
163
GLShader *shader = shaderManager->pushShader(ShaderManager::GenericShader);
164
shader->setUniform(GLShader::ScreenTransformation, matrix);
169
Scene::paintGenericScreen(mask, data);
172
shaderManager->popShader();
177
void SceneOpenGL::paintBackground(QRegion region)
179
PaintClipper pc(region);
180
if (!PaintClipper::clip()) {
181
glClearColor(0, 0, 0, 1);
182
glClear(GL_COLOR_BUFFER_BIT);
185
if (pc.clip() && pc.paintArea().isEmpty())
186
return; // no background to paint
187
QVector<float> verts;
188
for (PaintClipper::Iterator iterator; !iterator.isDone(); iterator.next()) {
189
QRect r = iterator.boundingRect();
190
verts << r.x() + r.width() << r.y();
191
verts << r.x() << r.y();
192
verts << r.x() << r.y() + r.height();
193
verts << r.x() << r.y() + r.height();
194
verts << r.x() + r.width() << r.y() + r.height();
195
verts << r.x() + r.width() << r.y();
197
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
199
vbo->setUseColor(true);
200
vbo->setData(verts.count() / 2, 2, verts.data(), NULL);
201
const bool useShader = ShaderManager::instance()->isValid();
203
GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::ColorShader);
204
shader->setUniform(GLShader::Offset, QVector2D(0, 0));
206
vbo->render(GL_TRIANGLES);
208
ShaderManager::instance()->popShader();
212
void SceneOpenGL::windowAdded(Toplevel* c)
214
assert(!windows.contains(c));
215
windows[ c ] = new Window(c);
216
c->effectWindow()->setSceneWindow(windows[ c ]);
218
windows[ c ]->updateShadow(c->shadow());
221
void SceneOpenGL::windowClosed(Toplevel* c, Deleted* deleted)
223
assert(windows.contains(c));
224
if (deleted != NULL) {
225
// replace c with deleted
226
Window* w = windows.take(c);
227
w->updateToplevel(deleted);
229
w->shadow()->setToplevel(deleted);
231
windows[ deleted ] = w;
233
delete windows.take(c);
234
c->effectWindow()->setSceneWindow(NULL);
238
void SceneOpenGL::windowDeleted(Deleted* c)
240
assert(windows.contains(c));
241
delete windows.take(c);
242
c->effectWindow()->setSceneWindow(NULL);
245
void SceneOpenGL::windowGeometryShapeChanged(Toplevel* c)
247
if (!windows.contains(c)) // this is ok, shape is not valid
248
return; // by default
249
Window* w = windows[ c ];
251
w->checkTextureSize();
254
void SceneOpenGL::windowOpacityChanged(Toplevel*)
256
#if 0 // not really needed, windows are painted on every repaint
257
// and opacity is used when applying texture, not when
259
if (!windows.contains(c)) // this is ok, texture is created
261
Window* w = windows[ c ];
266
//****************************************
267
// SceneOpenGL::Texture
268
//****************************************
270
SceneOpenGL::Texture::Texture() : GLTexture()
275
SceneOpenGL::Texture::Texture(const Pixmap& pix, const QSize& size, int depth) : GLTexture()
278
load(pix, size, depth);
281
SceneOpenGL::Texture::Texture(const QPixmap& pix, GLenum target)
288
SceneOpenGL::Texture::~Texture()
293
void SceneOpenGL::Texture::createTexture()
295
glGenTextures(1, &mTexture);
298
void SceneOpenGL::Texture::discard()
300
if (mTexture != None)
302
GLTexture::discard();
305
QRegion SceneOpenGL::Texture::optimizeBindDamage(const QRegion& reg, int limit)
307
if (reg.rects().count() <= 1)
309
// try to reduce the number of rects, as especially with SHM mode every rect
310
// causes X roundtrip, even for very small areas - so, when the size difference
311
// between all the areas and the bounding rectangle is small, simply use
312
// only the bounding rectangle
314
foreach (const QRect & r, reg.rects())
315
size += r.width() * r.height();
316
if (reg.boundingRect().width() * reg.boundingRect().height() - size < limit)
317
return reg.boundingRect();
321
bool SceneOpenGL::Texture::load(const Pixmap& pix, const QSize& size,
326
return load(pix, size, depth,
327
QRegion(0, 0, size.width(), size.height()));
330
bool SceneOpenGL::Texture::load(const QImage& image, GLenum target)
334
return load(QPixmap::fromImage(image), target);
337
bool SceneOpenGL::Texture::load(const QPixmap& pixmap, GLenum target)
342
// Checking whether QPixmap comes with its own X11 Pixmap
343
if (Extensions::nonNativePixmaps()) {
344
return GLTexture::load(pixmap.toImage(), target);
349
// use the X11 pixmap provided by Qt
350
return load(pixmap.handle(), pixmap.size(), pixmap.depth());
353
//****************************************
354
// SceneOpenGL::Window
355
//****************************************
357
SceneOpenGL::Window::Window(Toplevel* c)
367
SceneOpenGL::Window::~Window()
372
// Bind the window pixmap to an OpenGL texture.
373
bool SceneOpenGL::Window::bindTexture()
375
#ifndef KWIN_HAVE_OPENGLES
376
if (texture.texture() != None && toplevel->damage().isEmpty()) {
377
// texture doesn't need updating, just bind it
378
glBindTexture(texture.target(), texture.texture());
382
// Get the pixmap with the window contents
383
Pixmap pix = toplevel->windowPixmap();
386
bool success = texture.load(pix, toplevel->size(), toplevel->depth(),
389
toplevel->resetDamage(QRect(toplevel->clientPos(), toplevel->clientSize()));
391
kDebug(1212) << "Failed to bind window";
395
void SceneOpenGL::Window::discardTexture()
398
topTexture.discard();
399
leftTexture.discard();
400
rightTexture.discard();
401
bottomTexture.discard();
404
// This call is used in SceneOpenGL::windowGeometryShapeChanged(),
405
// which originally called discardTexture(), however this was causing performance
406
// problems with the launch feedback icon - large number of texture rebinds.
407
// Since the launch feedback icon does not resize, only changes shape, it
408
// is not necessary to rebind the texture (with no strict binding), therefore
409
// discard the texture only if size changes.
410
void SceneOpenGL::Window::checkTextureSize()
412
if (texture.size() != size())
416
// when the window's composite pixmap is discarded, undo binding it to the texture
417
void SceneOpenGL::Window::pixmapDiscarded()
422
QMatrix4x4 SceneOpenGL::Window::transformation(int mask, const WindowPaintData &data) const
425
matrix.translate(x(), y());
427
if (!(mask & PAINT_WINDOW_TRANSFORMED))
430
matrix.translate(data.xTranslate, data.yTranslate, data.zTranslate);
431
matrix.scale(data.xScale, data.yScale, data.zScale);
436
// Apply the rotation
437
const qreal xAxis = (data.rotation->axis == RotationData::XAxis ? 1.0 : 0.0);
438
const qreal yAxis = (data.rotation->axis == RotationData::YAxis ? 1.0 : 0.0);
439
const qreal zAxis = (data.rotation->axis == RotationData::ZAxis ? 1.0 : 0.0);
441
matrix.translate(data.rotation->xRotationPoint,
442
data.rotation->yRotationPoint,
443
data.rotation->zRotationPoint);
445
matrix.rotate(data.rotation->angle, xAxis, yAxis, zAxis);
447
matrix.translate(-data.rotation->xRotationPoint,
448
-data.rotation->yRotationPoint,
449
-data.rotation->zRotationPoint);
455
void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData data)
457
// check if there is something to paint (e.g. don't paint if the window
458
// is only opaque and only PAINT_WINDOW_TRANSLUCENT is requested)
459
/* HACK: It seems this causes painting glitches, disable temporarily
460
bool opaque = isOpaque() && data.opacity == 1.0;
461
if (( mask & PAINT_WINDOW_OPAQUE ) ^ ( mask & PAINT_WINDOW_TRANSLUCENT ))
462
{ // We are only painting either opaque OR translucent windows, not both
463
if ( mask & PAINT_WINDOW_OPAQUE && !opaque )
464
return; // Only painting opaque and window is translucent
465
if ( mask & PAINT_WINDOW_TRANSLUCENT && opaque )
466
return; // Only painting translucent and window is opaque
469
// Intersect the clip region with the rectangle the window occupies on the screen
470
if (!(mask & (PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED)))
471
region &= toplevel->visibleRect();
473
if (region.isEmpty())
479
// Update the texture filter
480
if (options->glSmoothScale != 0 &&
481
(mask & (PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED)))
482
filter = ImageFilterGood;
484
filter = ImageFilterFast;
486
texture.setFilter(filter == ImageFilterGood ? GL_LINEAR : GL_NEAREST);
488
bool sceneShader = false;
490
if (!data.shader && ShaderManager::instance()->isValid()) {
491
// set the shader for uniform initialising in paint decoration
492
if ((mask & PAINT_WINDOW_TRANSFORMED) || (mask & PAINT_SCREEN_TRANSFORMED)) {
493
data.shader = ShaderManager::instance()->pushShader(ShaderManager::GenericShader);
495
data.shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader);
496
data.shader->setUniform(GLShader::Offset, QVector2D(x(), y()));
501
const QMatrix4x4 windowTransformation = transformation(mask, data);
504
data.shader->setUniform(GLShader::WindowTransformation, windowTransformation);
507
pushMatrix(windowTransformation);
509
WindowQuadList decoration = data.quads.select(WindowQuadDecoration);
511
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
516
paintShadow(WindowQuadShadowTop, region, data);
517
paintShadow(WindowQuadShadowTopRight, region, data);
518
paintShadow(WindowQuadShadowRight, region, data);
519
paintShadow(WindowQuadShadowBottomRight, region, data);
520
paintShadow(WindowQuadShadowBottom, region, data);
521
paintShadow(WindowQuadShadowBottomLeft, region, data);
522
paintShadow(WindowQuadShadowLeft, region, data);
523
paintShadow(WindowQuadShadowTopLeft, region, data);
526
Client *client = dynamic_cast<Client*>(toplevel);
527
Deleted *deleted = dynamic_cast<Deleted*>(toplevel);
528
if (client || deleted) {
529
bool noBorder = true;
530
bool updateDeco = false;
531
const QPixmap *left = NULL;
532
const QPixmap *top = NULL;
533
const QPixmap *right = NULL;
534
const QPixmap *bottom = NULL;
535
QRect topRect, leftRect, rightRect, bottomRect;
536
if (client && !client->noBorder()) {
538
updateDeco = client->decorationPixmapRequiresRepaint();
539
client->ensureDecorationPixmapsPainted();
541
client->layoutDecorationRects(leftRect, topRect, rightRect, bottomRect, Client::WindowRelative);
543
left = client->leftDecoPixmap();
544
top = client->topDecoPixmap();
545
right = client->rightDecoPixmap();
546
bottom = client->bottomDecoPixmap();
548
if (deleted && !deleted->noBorder()) {
550
left = deleted->leftDecoPixmap();
551
top = deleted->topDecoPixmap();
552
right = deleted->rightDecoPixmap();
553
bottom = deleted->bottomDecoPixmap();
554
deleted->layoutDecorationRects(leftRect, topRect, rightRect, bottomRect);
557
WindowQuadList topList, leftList, rightList, bottomList;
559
foreach (const WindowQuad & quad, decoration) {
560
if (topRect.contains(QPoint(quad.originalLeft(), quad.originalTop()))) {
561
topList.append(quad);
564
if (bottomRect.contains(QPoint(quad.originalLeft(), quad.originalTop()))) {
565
bottomList.append(quad);
568
if (leftRect.contains(QPoint(quad.originalLeft(), quad.originalTop()))) {
569
leftList.append(quad);
572
if (rightRect.contains(QPoint(quad.originalLeft(), quad.originalTop()))) {
573
rightList.append(quad);
578
paintDecoration(top, DecorationTop, region, topRect, data, topList, updateDeco);
579
paintDecoration(left, DecorationLeft, region, leftRect, data, leftList, updateDeco);
580
paintDecoration(right, DecorationRight, region, rightRect, data, rightList, updateDeco);
581
paintDecoration(bottom, DecorationBottom, region, bottomRect, data, bottomList, updateDeco);
586
if (!(mask & PAINT_DECORATION_ONLY)) {
588
prepareStates(Content, data.opacity * data.contents_opacity, data.brightness, data.saturation, data.shader);
589
renderQuads(mask, region, data.quads.select(WindowQuadContents), toplevel->size(), texture.getYInverted());
590
restoreStates(Content, data.opacity * data.contents_opacity, data.brightness, data.saturation, data.shader);
592
#ifndef KWIN_HAVE_OPENGLES
593
if (static_cast<SceneOpenGL*>(scene)->debug) {
594
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
595
renderQuads(mask, region, data.quads.select(WindowQuadContents), toplevel->size(), texture.getYInverted());
596
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
602
ShaderManager::instance()->popShader();
609
void SceneOpenGL::Window::paintDecoration(const QPixmap* decoration, TextureType decorationType, const QRegion& region, const QRect& rect, const WindowPaintData& data, const WindowQuadList& quads, bool updateDeco)
613
SceneOpenGL::Texture* decorationTexture;
614
switch(decorationType) {
616
decorationTexture = &topTexture;
619
decorationTexture = &leftTexture;
621
case DecorationRight:
622
decorationTexture = &rightTexture;
624
case DecorationBottom:
625
decorationTexture = &bottomTexture;
630
if (decorationTexture->texture() != None && !updateDeco) {
631
// texture doesn't need updating, just bind it
632
glBindTexture(decorationTexture->target(), decorationTexture->texture());
633
} else if (!decoration->isNull()) {
634
bool success = decorationTexture->load(*decoration);
636
kDebug(1212) << "Failed to bind decoartion";
641
if (filter == ImageFilterGood)
642
decorationTexture->setFilter(GL_LINEAR);
644
decorationTexture->setFilter(GL_NEAREST);
645
decorationTexture->setWrapMode(GL_CLAMP_TO_EDGE);
646
decorationTexture->bind();
648
prepareStates(decorationType, data.opacity * data.decoration_opacity, data.brightness, data.saturation, data.shader);
649
makeDecorationArrays(quads, rect, decorationTexture->getYInverted());
650
GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES);
651
restoreStates(decorationType, data.opacity * data.decoration_opacity, data.brightness, data.saturation, data.shader);
652
decorationTexture->unbind();
653
#ifndef KWIN_HAVE_OPENGLES
654
if (static_cast<SceneOpenGL*>(scene)->debug) {
655
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
656
GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES);
657
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
662
void SceneOpenGL::Window::paintShadow(WindowQuadType type, const QRegion ®ion, const WindowPaintData &data)
664
WindowQuadList quads = data.quads.select(type);
665
Texture *texture = static_cast<SceneOpenGLShadow*>(m_shadow)->textureForQuadType(type);
669
if (filter == ImageFilterGood)
670
texture->setFilter(GL_LINEAR);
672
texture->setFilter(GL_NEAREST);
673
texture->setWrapMode(GL_CLAMP_TO_EDGE);
675
prepareStates(Shadow, data.opacity, data.brightness, data.saturation, data.shader, texture);
676
renderQuads(0, region, quads, QSizeF(1.0, 1.0), texture->getYInverted());
677
restoreStates(Shadow, data.opacity, data.brightness, data.saturation, data.shader, texture);
679
#ifndef KWIN_HAVE_OPENGLES
680
if (static_cast<SceneOpenGL*>(scene)->debug) {
681
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
682
renderQuads(0, region, quads, QSizeF(1.0, 1.0), texture->getYInverted());
683
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
688
void SceneOpenGL::Window::makeDecorationArrays(const WindowQuadList& quads, const QRect& rect, bool y_inverted) const
690
QVector<float> vertices;
691
QVector<float> texcoords;
692
vertices.reserve(quads.count() * 6 * 2);
693
texcoords.reserve(quads.count() * 6 * 2);
694
float width = rect.width();
695
float height = rect.height();
696
foreach (const WindowQuad & quad, quads) {
697
vertices << quad[ 1 ].x();
698
vertices << quad[ 1 ].y();
699
vertices << quad[ 0 ].x();
700
vertices << quad[ 0 ].y();
701
vertices << quad[ 3 ].x();
702
vertices << quad[ 3 ].y();
703
vertices << quad[ 3 ].x();
704
vertices << quad[ 3 ].y();
705
vertices << quad[ 2 ].x();
706
vertices << quad[ 2 ].y();
707
vertices << quad[ 1 ].x();
708
vertices << quad[ 1 ].y();
711
texcoords << (float)(quad.originalRight() - rect.x()) / width;
712
texcoords << (float)(quad.originalTop() - rect.y()) / height;
713
texcoords << (float)(quad.originalLeft() - rect.x()) / width;
714
texcoords << (float)(quad.originalTop() - rect.y()) / height;
715
texcoords << (float)(quad.originalLeft() - rect.x()) / width;
716
texcoords << (float)(quad.originalBottom() - rect.y()) / height;
717
texcoords << (float)(quad.originalLeft() - rect.x()) / width;
718
texcoords << (float)(quad.originalBottom() - rect.y()) / height;
719
texcoords << (float)(quad.originalRight() - rect.x()) / width;
720
texcoords << (float)(quad.originalBottom() - rect.y()) / height;
721
texcoords << (float)(quad.originalRight() - rect.x()) / width;
722
texcoords << (float)(quad.originalTop() - rect.y()) / height;
724
texcoords << (float)(quad.originalRight() - rect.x()) / width;
725
texcoords << 1.0f - (float)(quad.originalTop() - rect.y()) / height;
726
texcoords << (float)(quad.originalLeft() - rect.x()) / width;
727
texcoords << 1.0f - (float)(quad.originalTop() - rect.y()) / height;
728
texcoords << (float)(quad.originalLeft() - rect.x()) / width;
729
texcoords << 1.0f - (float)(quad.originalBottom() - rect.y()) / height;
730
texcoords << (float)(quad.originalLeft() - rect.x()) / width;
731
texcoords << 1.0f - (float)(quad.originalBottom() - rect.y()) / height;
732
texcoords << (float)(quad.originalRight() - rect.x()) / width;
733
texcoords << 1.0f - (float)(quad.originalBottom() - rect.y()) / height;
734
texcoords << (float)(quad.originalRight() - rect.x()) / width;
735
texcoords << 1.0f - (float)(quad.originalTop() - rect.y()) / height;
738
GLVertexBuffer::streamingBuffer()->setData(quads.count() * 6, 2, vertices.data(), texcoords.data());
741
void SceneOpenGL::Window::renderQuads(int, const QRegion& region, const WindowQuadList& quads, const QSizeF &size, bool yInverted)
748
quads.makeArrays(&vertices, &texcoords, size, yInverted);
749
GLVertexBuffer::streamingBuffer()->setData(quads.count() * 6, 2, vertices, texcoords);
750
GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES);
755
void SceneOpenGL::Window::prepareStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader)
758
prepareShaderRenderStates(type, opacity, brightness, saturation, shader);
771
case DecorationRight:
774
case DecorationBottom:
775
tex = &bottomTexture;
780
prepareStates(type, opacity, brightness, saturation, shader, tex);
784
void SceneOpenGL::Window::prepareStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader, Texture *texture)
787
prepareShaderRenderStates(type, opacity, brightness, saturation, shader);
789
prepareRenderStates(type, opacity, brightness, saturation, texture);
793
void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader)
795
// setup blending of transparent windows
796
#ifndef KWIN_HAVE_OPENGLES
797
glPushAttrib(GL_ENABLE_BIT);
799
bool opaque = isOpaque() && opacity == 1.0;
800
bool alpha = toplevel->hasAlpha() || type != Content;
806
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
808
glBlendColor((float)opacity, (float)opacity, (float)opacity, (float)opacity);
809
glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_ALPHA);
813
const float rgb = brightness * opacity;
814
const float a = opacity;
816
shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a));
817
shader->setUniform(GLShader::Saturation, saturation);
818
shader->setUniform(GLShader::AlphaToOne, opaque ? 1 : 0);
821
void SceneOpenGL::Window::prepareRenderStates(TextureType type, double opacity, double brightness, double saturation, Texture *tex)
823
#ifdef KWIN_HAVE_OPENGLES
832
if (type == Content) {
833
alpha = toplevel->hasAlpha();
834
opaque = isOpaque() && opacity == 1.0;
839
// setup blending of transparent windows
840
glPushAttrib(GL_ENABLE_BIT);
843
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
845
if (saturation != 1.0 && tex->saturationSupported()) {
846
// First we need to get the color from [0; 1] range to [0.5; 1] range
847
glActiveTexture(GL_TEXTURE0);
848
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
849
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
850
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
851
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
852
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
853
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
854
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
855
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
856
const float scale_constant[] = { 1.0, 1.0, 1.0, 0.5};
857
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, scale_constant);
860
// Then we take dot product of the result of previous pass and
861
// saturation_constant. This gives us completely unsaturated
863
// Note that both operands have to be in range [0.5; 1] since opengl
864
// automatically substracts 0.5 from them
865
glActiveTexture(GL_TEXTURE1);
866
float saturation_constant[] = { 0.5 + 0.5 * 0.30, 0.5 + 0.5 * 0.59, 0.5 + 0.5 * 0.11, saturation };
867
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
868
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
869
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
870
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
871
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
872
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
873
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, saturation_constant);
876
// Finally we need to interpolate between the original image and the
877
// greyscale image to get wanted level of saturation
878
glActiveTexture(GL_TEXTURE2);
879
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
880
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
881
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
882
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
883
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
884
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
885
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
886
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
887
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, saturation_constant);
888
// Also replace alpha by primary color's alpha here
889
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
890
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
891
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
892
// And make primary color contain the wanted opacity
893
glColor4f(opacity, opacity, opacity, opacity);
896
if (alpha || brightness != 1.0f) {
897
glActiveTexture(GL_TEXTURE3);
898
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
899
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
900
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
901
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
902
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
903
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
904
// The color has to be multiplied by both opacity and brightness
905
float opacityByBrightness = opacity * brightness;
906
glColor4f(opacityByBrightness, opacityByBrightness, opacityByBrightness, opacity);
908
// Multiply original texture's alpha by our opacity
909
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
910
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0);
911
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
912
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR);
913
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
915
// Alpha will be taken from previous stage
916
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
917
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
918
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
923
glActiveTexture(GL_TEXTURE0);
924
} else if (opacity != 1.0 || brightness != 1.0) {
925
// the window is additionally configured to have its opacity adjusted,
927
float opacityByBrightness = opacity * brightness;
929
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
930
glColor4f(opacityByBrightness, opacityByBrightness, opacityByBrightness,
933
// Multiply color by brightness and replace alpha by opacity
934
float constant[] = { opacityByBrightness, opacityByBrightness, opacityByBrightness, opacity };
935
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
936
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
937
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
938
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
939
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
940
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
941
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
942
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);
943
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
945
} else if (!alpha && opaque) {
946
float constant[] = { 1.0, 1.0, 1.0, 1.0 };
947
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
948
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
949
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
950
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
951
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);
952
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
957
void SceneOpenGL::Window::restoreStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader)
960
restoreShaderRenderStates(type, opacity, brightness, saturation, shader);
973
case DecorationRight:
976
case DecorationBottom:
977
tex = &bottomTexture;
982
restoreStates(type, opacity, brightness, saturation, shader, tex);
986
void SceneOpenGL::Window::restoreStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader, Texture *texture)
989
restoreShaderRenderStates(type, opacity, brightness, saturation, shader);
991
restoreRenderStates(type, opacity, brightness, saturation, texture);
995
void SceneOpenGL::Window::restoreShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader)
997
Q_UNUSED(brightness);
998
Q_UNUSED(saturation);
1000
bool opaque = isOpaque() && opacity == 1.0;
1001
if (type != Content)
1004
glDisable(GL_BLEND);
1006
ShaderManager::instance()->getBoundShader()->setUniform(GLShader::AlphaToOne, 0);
1007
#ifndef KWIN_HAVE_OPENGLES
1008
glPopAttrib(); // ENABLE_BIT
1012
void SceneOpenGL::Window::restoreRenderStates(TextureType type, double opacity, double brightness, double saturation, Texture *tex)
1015
#ifdef KWIN_HAVE_OPENGLES
1017
Q_UNUSED(brightness)
1018
Q_UNUSED(saturation)
1021
if (opacity != 1.0 || saturation != 1.0 || brightness != 1.0f) {
1022
if (saturation != 1.0 && tex->saturationSupported()) {
1023
glActiveTexture(GL_TEXTURE3);
1024
glDisable(tex->target());
1025
glActiveTexture(GL_TEXTURE2);
1026
glDisable(tex->target());
1027
glActiveTexture(GL_TEXTURE1);
1028
glDisable(tex->target());
1029
glActiveTexture(GL_TEXTURE0);
1032
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1033
glColor4f(0, 0, 0, 0);
1035
glPopAttrib(); // ENABLE_BIT
1039
//****************************************
1040
// SceneOpenGL::EffectFrame
1041
//****************************************
1043
SceneOpenGL::Texture* SceneOpenGL::EffectFrame::m_unstyledTexture = NULL;
1044
QPixmap* SceneOpenGL::EffectFrame::m_unstyledPixmap = NULL;
1046
SceneOpenGL::EffectFrame::EffectFrame(EffectFrameImpl* frame)
1047
: Scene::EffectFrame(frame)
1049
, m_textTexture(NULL)
1050
, m_oldTextTexture(NULL)
1051
, m_textPixmap(NULL)
1052
, m_iconTexture(NULL)
1053
, m_oldIconTexture(NULL)
1054
, m_selectionTexture(NULL)
1055
, m_unstyledVBO(NULL)
1057
if (m_effectFrame->style() == EffectFrameUnstyled && !m_unstyledTexture) {
1058
updateUnstyledTexture();
1062
SceneOpenGL::EffectFrame::~EffectFrame()
1065
delete m_textTexture;
1066
delete m_textPixmap;
1067
delete m_oldTextTexture;
1068
delete m_iconTexture;
1069
delete m_oldIconTexture;
1070
delete m_selectionTexture;
1071
delete m_unstyledVBO;
1074
void SceneOpenGL::EffectFrame::free()
1079
delete m_textTexture;
1080
m_textTexture = NULL;
1081
delete m_textPixmap;
1082
m_textPixmap = NULL;
1083
delete m_iconTexture;
1084
m_iconTexture = NULL;
1085
delete m_selectionTexture;
1086
m_selectionTexture = NULL;
1087
delete m_unstyledVBO;
1088
m_unstyledVBO = NULL;
1089
delete m_oldIconTexture;
1090
m_oldIconTexture = NULL;
1091
delete m_oldTextTexture;
1092
m_oldTextTexture = NULL;
1095
void SceneOpenGL::EffectFrame::freeIconFrame()
1097
delete m_iconTexture;
1098
m_iconTexture = NULL;
1101
void SceneOpenGL::EffectFrame::freeTextFrame()
1103
delete m_textTexture;
1104
m_textTexture = NULL;
1105
delete m_textPixmap;
1106
m_textPixmap = NULL;
1109
void SceneOpenGL::EffectFrame::freeSelection()
1111
delete m_selectionTexture;
1112
m_selectionTexture = NULL;
1115
void SceneOpenGL::EffectFrame::crossFadeIcon()
1117
delete m_oldIconTexture;
1118
m_oldIconTexture = m_iconTexture;
1119
m_iconTexture = NULL;
1122
void SceneOpenGL::EffectFrame::crossFadeText()
1124
delete m_oldTextTexture;
1125
m_oldTextTexture = m_textTexture;
1126
m_textTexture = NULL;
1129
void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double frameOpacity)
1131
if (m_effectFrame->geometry().isEmpty())
1132
return; // Nothing to display
1134
region = infiniteRegion(); // TODO: Old region doesn't seem to work with OpenGL
1136
GLShader* shader = m_effectFrame->shader();
1137
bool sceneShader = false;
1138
if (!shader && ShaderManager::instance()->isValid()) {
1139
shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader);
1141
} else if (shader) {
1142
ShaderManager::instance()->pushShader(shader);
1147
shader->setUniform(GLShader::Offset, QVector2D(0, 0));
1149
shader->setUniform(GLShader::ModulationConstant, QVector4D(1.0, 1.0, 1.0, 1.0));
1150
shader->setUniform(GLShader::Saturation, 1.0f);
1151
shader->setUniform(GLShader::AlphaToOne, 0);
1154
#ifndef KWIN_HAVE_OPENGLES
1155
glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT);
1158
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1159
#ifndef KWIN_HAVE_OPENGLES
1161
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1163
// TODO: drop the push matrix
1167
// Render the actual frame
1168
if (m_effectFrame->style() == EffectFrameUnstyled) {
1169
if (!m_unstyledVBO) {
1170
m_unstyledVBO = new GLVertexBuffer(GLVertexBuffer::Static);
1171
QRect area = m_effectFrame->geometry();
1173
area.adjust(-5, -5, 5, 5);
1175
const int roundness = 5;
1176
QVector<float> verts, texCoords;
1178
texCoords.reserve(84);
1181
verts << area.left() << area.top();
1182
texCoords << 0.0f << 0.0f;
1183
verts << area.left() << area.top() + roundness;
1184
texCoords << 0.0f << 0.5f;
1185
verts << area.left() + roundness << area.top();
1186
texCoords << 0.5f << 0.0f;
1187
verts << area.left() + roundness << area.top() + roundness;
1188
texCoords << 0.5f << 0.5f;
1189
verts << area.left() << area.top() + roundness;
1190
texCoords << 0.0f << 0.5f;
1191
verts << area.left() + roundness << area.top();
1192
texCoords << 0.5f << 0.0f;
1194
verts << area.left() + roundness << area.top();
1195
texCoords << 0.5f << 0.0f;
1196
verts << area.left() + roundness << area.top() + roundness;
1197
texCoords << 0.5f << 0.5f;
1198
verts << area.right() - roundness << area.top();
1199
texCoords << 0.5f << 0.0f;
1200
verts << area.left() + roundness << area.top() + roundness;
1201
texCoords << 0.5f << 0.5f;
1202
verts << area.right() - roundness << area.top() + roundness;
1203
texCoords << 0.5f << 0.5f;
1204
verts << area.right() - roundness << area.top();
1205
texCoords << 0.5f << 0.0f;
1207
verts << area.right() - roundness << area.top();
1208
texCoords << 0.5f << 0.0f;
1209
verts << area.right() - roundness << area.top() + roundness;
1210
texCoords << 0.5f << 0.5f;
1211
verts << area.right() << area.top();
1212
texCoords << 1.0f << 0.0f;
1213
verts << area.right() - roundness << area.top() + roundness;
1214
texCoords << 0.5f << 0.5f;
1215
verts << area.right() << area.top() + roundness;
1216
texCoords << 1.0f << 0.5f;
1217
verts << area.right() << area.top();
1218
texCoords << 1.0f << 0.0f;
1220
verts << area.left() << area.bottom() - roundness;
1221
texCoords << 0.0f << 0.5f;
1222
verts << area.left() << area.bottom();
1223
texCoords << 0.0f << 1.0f;
1224
verts << area.left() + roundness << area.bottom() - roundness;
1225
texCoords << 0.5f << 0.5f;
1226
verts << area.left() + roundness << area.bottom();
1227
texCoords << 0.5f << 1.0f;
1228
verts << area.left() << area.bottom();
1229
texCoords << 0.0f << 1.0f;
1230
verts << area.left() + roundness << area.bottom() - roundness;
1231
texCoords << 0.5f << 0.5f;
1233
verts << area.left() + roundness << area.bottom() - roundness;
1234
texCoords << 0.5f << 0.5f;
1235
verts << area.left() + roundness << area.bottom();
1236
texCoords << 0.5f << 1.0f;
1237
verts << area.right() - roundness << area.bottom() - roundness;
1238
texCoords << 0.5f << 0.5f;
1239
verts << area.left() + roundness << area.bottom();
1240
texCoords << 0.5f << 1.0f;
1241
verts << area.right() - roundness << area.bottom();
1242
texCoords << 0.5f << 1.0f;
1243
verts << area.right() - roundness << area.bottom() - roundness;
1244
texCoords << 0.5f << 0.5f;
1246
verts << area.right() - roundness << area.bottom() - roundness;
1247
texCoords << 0.5f << 0.5f;
1248
verts << area.right() - roundness << area.bottom();
1249
texCoords << 0.5f << 1.0f;
1250
verts << area.right() << area.bottom() - roundness;
1251
texCoords << 1.0f << 0.5f;
1252
verts << area.right() - roundness << area.bottom();
1253
texCoords << 0.5f << 1.0f;
1254
verts << area.right() << area.bottom();
1255
texCoords << 1.0f << 1.0f;
1256
verts << area.right() << area.bottom() - roundness;
1257
texCoords << 1.0f << 0.5f;
1259
verts << area.left() << area.top() + roundness;
1260
texCoords << 0.0f << 0.5f;
1261
verts << area.left() << area.bottom() - roundness;
1262
texCoords << 0.0f << 0.5f;
1263
verts << area.right() << area.top() + roundness;
1264
texCoords << 1.0f << 0.5f;
1265
verts << area.left() << area.bottom() - roundness;
1266
texCoords << 0.0f << 0.5f;
1267
verts << area.right() << area.bottom() - roundness;
1268
texCoords << 1.0f << 0.5f;
1269
verts << area.right() << area.top() + roundness;
1270
texCoords << 1.0f << 0.5f;
1272
m_unstyledVBO->setData(verts.count() / 2, 2, verts.data(), texCoords.data());
1276
const float a = opacity * frameOpacity;
1277
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
1279
#ifndef KWIN_HAVE_OPENGLES
1281
glColor4f(0.0, 0.0, 0.0, opacity * frameOpacity);
1284
m_unstyledTexture->bind();
1285
const QPoint pt = m_effectFrame->geometry().topLeft();
1287
shader->setUniform(GLShader::Offset, QVector2D(pt.x(), pt.y()));
1289
QMatrix4x4 translation;
1290
translation.translate(pt.x(), pt.y());
1292
shader->setUniform(GLShader::WindowTransformation, translation);
1294
pushMatrix(translation);
1297
m_unstyledVBO->render(region, GL_TRIANGLES);
1300
shader->setUniform(GLShader::WindowTransformation, QMatrix4x4());
1305
m_unstyledTexture->unbind();
1306
} else if (m_effectFrame->style() == EffectFrameStyled) {
1307
if (!m_texture) // Lazy creation
1311
const float a = opacity * frameOpacity;
1312
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
1314
#ifndef KWIN_HAVE_OPENGLES
1316
glColor4f(1.0, 1.0, 1.0, opacity * frameOpacity);
1319
qreal left, top, right, bottom;
1320
m_effectFrame->frame().getMargins(left, top, right, bottom); // m_geometry is the inner geometry
1321
m_texture->render(region, m_effectFrame->geometry().adjusted(-left, -top, right, bottom));
1322
m_texture->unbind();
1325
if (!m_effectFrame->selection().isNull()) {
1326
if (!m_selectionTexture) { // Lazy creation
1327
QPixmap pixmap = m_effectFrame->selectionFrame().framePixmap();
1328
if (!pixmap.isNull())
1329
m_selectionTexture = new Texture(pixmap);
1331
if (m_selectionTexture) {
1333
const float a = opacity * frameOpacity;
1334
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
1336
#ifndef KWIN_HAVE_OPENGLES
1338
glColor4f(1.0, 1.0, 1.0, opacity * frameOpacity);
1340
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1341
m_selectionTexture->bind();
1342
m_selectionTexture->render(region, m_effectFrame->selection());
1343
m_selectionTexture->unbind();
1344
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1349
if (!m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty()) {
1350
QPoint topLeft(m_effectFrame->geometry().x(),
1351
m_effectFrame->geometry().center().y() - m_effectFrame->iconSize().height() / 2);
1353
if (m_effectFrame->isCrossFade() && m_oldIconTexture) {
1355
const float a = opacity * (1.0 - m_effectFrame->crossFadeProgress());
1356
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
1358
#ifndef KWIN_HAVE_OPENGLES
1360
glColor4f(1.0, 1.0, 1.0, opacity * (1.0 - m_effectFrame->crossFadeProgress()));
1363
m_oldIconTexture->bind();
1364
m_oldIconTexture->render(region, QRect(topLeft, m_effectFrame->iconSize()));
1365
m_oldIconTexture->unbind();
1367
const float a = opacity * m_effectFrame->crossFadeProgress();
1368
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
1370
#ifndef KWIN_HAVE_OPENGLES
1372
glColor4f(1.0, 1.0, 1.0, opacity * m_effectFrame->crossFadeProgress());
1376
const QVector4D constant(opacity, opacity, opacity, opacity);
1377
shader->setUniform(GLShader::ModulationConstant, constant);
1379
#ifndef KWIN_HAVE_OPENGLES
1381
glColor4f(1.0, 1.0, 1.0, opacity);
1385
if (!m_iconTexture) { // lazy creation
1386
m_iconTexture = new Texture(m_effectFrame->icon());
1388
m_iconTexture->bind();
1389
m_iconTexture->render(region, QRect(topLeft, m_effectFrame->iconSize()));
1390
m_iconTexture->unbind();
1394
if (!m_effectFrame->text().isEmpty()) {
1395
if (m_effectFrame->isCrossFade() && m_oldTextTexture) {
1397
const float a = opacity * (1.0 - m_effectFrame->crossFadeProgress());
1398
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
1400
#ifndef KWIN_HAVE_OPENGLES
1402
glColor4f(1.0, 1.0, 1.0, opacity *(1.0 - m_effectFrame->crossFadeProgress()));
1405
m_oldTextTexture->bind();
1406
m_oldTextTexture->render(region, m_effectFrame->geometry());
1407
m_oldTextTexture->unbind();
1409
const float a = opacity * m_effectFrame->crossFadeProgress();
1410
shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
1412
#ifndef KWIN_HAVE_OPENGLES
1414
glColor4f(1.0, 1.0, 1.0, opacity * m_effectFrame->crossFadeProgress());
1418
const QVector4D constant(opacity, opacity, opacity, opacity);
1419
shader->setUniform(GLShader::ModulationConstant, constant);
1421
#ifndef KWIN_HAVE_OPENGLES
1423
glColor4f(1.0, 1.0, 1.0, opacity);
1426
if (!m_textTexture) // Lazy creation
1427
updateTextTexture();
1428
m_textTexture->bind();
1429
m_textTexture->render(region, m_effectFrame->geometry());
1430
m_textTexture->unbind();
1434
ShaderManager::instance()->popShader();
1436
glDisable(GL_BLEND);
1437
#ifndef KWIN_HAVE_OPENGLES
1443
void SceneOpenGL::EffectFrame::updateTexture()
1447
if (m_effectFrame->style() == EffectFrameStyled) {
1448
QPixmap pixmap = m_effectFrame->frame().framePixmap();
1449
m_texture = new Texture(pixmap);
1453
void SceneOpenGL::EffectFrame::updateTextTexture()
1455
delete m_textTexture;
1457
delete m_textPixmap;
1460
if (m_effectFrame->text().isEmpty())
1463
// Determine position on texture to paint text
1464
QRect rect(QPoint(0, 0), m_effectFrame->geometry().size());
1465
if (!m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty())
1466
rect.setLeft(m_effectFrame->iconSize().width());
1468
// If static size elide text as required
1469
QString text = m_effectFrame->text();
1470
if (m_effectFrame->isStatic()) {
1471
QFontMetrics metrics(m_effectFrame->font());
1472
text = metrics.elidedText(text, Qt::ElideRight, rect.width());
1475
m_textPixmap = new QPixmap(m_effectFrame->geometry().size());
1476
m_textPixmap->fill(Qt::transparent);
1477
QPainter p(m_textPixmap);
1478
p.setFont(m_effectFrame->font());
1479
if (m_effectFrame->style() == EffectFrameStyled)
1480
p.setPen(m_effectFrame->styledTextColor());
1481
else // TODO: What about no frame? Custom color setting required
1482
p.setPen(Qt::white);
1483
p.drawText(rect, m_effectFrame->alignment(), text);
1485
m_textTexture = new Texture(*m_textPixmap);
1488
void SceneOpenGL::EffectFrame::updateUnstyledTexture()
1490
delete m_unstyledTexture;
1491
m_unstyledTexture = 0L;
1492
delete m_unstyledPixmap;
1493
m_unstyledPixmap = 0L;
1494
// Based off circle() from kwinxrenderutils.cpp
1496
m_unstyledPixmap = new QPixmap(2 * CS, 2 * CS);
1497
m_unstyledPixmap->fill(Qt::transparent);
1498
QPainter p(m_unstyledPixmap);
1499
p.setRenderHint(QPainter::Antialiasing);
1500
p.setPen(Qt::NoPen);
1501
p.setBrush(Qt::black);
1502
p.drawEllipse(m_unstyledPixmap->rect());
1505
m_unstyledTexture = new Texture(*m_unstyledPixmap);
1508
void SceneOpenGL::EffectFrame::cleanup()
1510
delete m_unstyledTexture;
1511
m_unstyledTexture = NULL;
1512
delete m_unstyledPixmap;
1513
m_unstyledPixmap = NULL;
1516
//****************************************
1517
// SceneOpenGL::Shadow
1518
//****************************************
1519
SceneOpenGLShadow::SceneOpenGLShadow(Toplevel *toplevel)
1524
SceneOpenGLShadow::~SceneOpenGLShadow()
1526
for (int i=0; i<ShadowElementsCount; ++i) {
1527
m_shadowTextures[i].discard();
1531
SceneOpenGL::Texture *SceneOpenGLShadow::textureForQuadType(WindowQuadType type)
1533
SceneOpenGL::Texture *texture = NULL;
1536
case WindowQuadShadowTop:
1537
texture = &m_shadowTextures[ShadowElementTop];
1538
pixmap = shadowPixmap(ShadowElementTop);
1540
case WindowQuadShadowTopRight:
1541
texture = &m_shadowTextures[ShadowElementTopRight];
1542
pixmap = shadowPixmap(ShadowElementTopRight);
1544
case WindowQuadShadowRight:
1545
texture = &m_shadowTextures[ShadowElementRight];
1546
pixmap = shadowPixmap(ShadowElementRight);
1548
case WindowQuadShadowBottomRight:
1549
texture = &m_shadowTextures[ShadowElementBottomRight];
1550
pixmap = shadowPixmap(ShadowElementBottomRight);
1552
case WindowQuadShadowBottom:
1553
texture = &m_shadowTextures[ShadowElementBottom];
1554
pixmap = shadowPixmap(ShadowElementBottom);
1556
case WindowQuadShadowBottomLeft:
1557
texture = &m_shadowTextures[ShadowElementBottomLeft];
1558
pixmap = shadowPixmap(ShadowElementBottomLeft);
1560
case WindowQuadShadowLeft:
1561
texture = &m_shadowTextures[ShadowElementLeft];
1562
pixmap = shadowPixmap(ShadowElementLeft);
1564
case WindowQuadShadowTopLeft:
1565
texture = &m_shadowTextures[ShadowElementTopLeft];
1566
pixmap = shadowPixmap(ShadowElementTopLeft);
1573
if (texture->texture() != None) {
1574
glBindTexture(texture->target(), texture->texture());
1575
} else if (!pixmap.isNull()) {
1576
const bool success = texture->load(pixmap);
1578
kDebug(1212) << "Failed to bind shadow pixmap";