~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kwin/scene_opengl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************
 
2
 KWin - the KDE window manager
 
3
 This file is part of the KDE project.
 
4
 
 
5
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
 
6
Copyright (C) 2009, 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
 
7
 
 
8
Based on glcompmgr code by Felix Bellaby.
 
9
Using code from Compiz and Beryl.
 
10
 
 
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.
 
15
 
 
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.
 
20
 
 
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
*********************************************************************/
 
24
 
 
25
 
 
26
/*
 
27
 This is the OpenGL-based compositing code. It is the primary and most powerful
 
28
 compositing backend.
 
29
 
 
30
Sources and other compositing managers:
 
31
=======================================
 
32
 
 
33
- http://opengl.org
 
34
    - documentation
 
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/)
 
38
 
 
39
- glcompmgr
 
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"
 
47
 
 
48
- compiz
 
49
    - git clone git://anongit.freedesktop.org/git/xorg/app/compiz
 
50
    - the ultimate <whatever>
 
51
    - glxcompmgr
 
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
 
54
            to understand
 
55
 
 
56
- beryl
 
57
    - a fork of Compiz
 
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/)
 
61
 
 
62
- libcm (metacity)
 
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
 
66
 
 
67
*/
 
68
 
 
69
#include "scene_opengl.h"
 
70
#include "kwinglplatform.h"
 
71
 
 
72
#include <kxerrorhandler.h>
 
73
 
 
74
#include <kwinglplatform.h>
 
75
 
 
76
#include "utils.h"
 
77
#include "client.h"
 
78
#include "deleted.h"
 
79
#include "effects.h"
 
80
 
 
81
#include <math.h>
 
82
 
 
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
 
86
 
 
87
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
 
88
 
 
89
#include <X11/extensions/Xcomposite.h>
 
90
 
 
91
#include <qpainter.h>
 
92
#include <QVector2D>
 
93
#include <QVector4D>
 
94
#include <QMatrix4x4>
 
95
 
 
96
namespace KWin
 
97
{
 
98
 
 
99
extern int currentRefreshRate();
 
100
 
 
101
//****************************************
 
102
// SceneOpenGL
 
103
//****************************************
 
104
 
 
105
bool SceneOpenGL::db; // destination drawable is double-buffered
 
106
 
 
107
#ifdef KWIN_HAVE_OPENGLES
 
108
#include "scene_opengl_egl.cpp"
 
109
#else
 
110
#include "scene_opengl_glx.cpp"
 
111
#endif
 
112
 
 
113
bool SceneOpenGL::initFailed() const
 
114
{
 
115
    return !init_ok;
 
116
}
 
117
 
 
118
bool SceneOpenGL::selectMode()
 
119
{
 
120
    if (!initDrawableConfigs())
 
121
        return false;
 
122
    return true;
 
123
}
 
124
 
 
125
QMatrix4x4 SceneOpenGL::transformation(int mask, const ScreenPaintData &data) const
 
126
{
 
127
    QMatrix4x4 matrix;
 
128
 
 
129
    if (!(mask & PAINT_SCREEN_TRANSFORMED))
 
130
        return matrix;
 
131
 
 
132
    matrix.translate(data.xTranslate, data.yTranslate, data.zTranslate);
 
133
    matrix.scale(data.xScale, data.yScale, data.zScale);
 
134
 
 
135
    if (!data.rotation)
 
136
        return matrix;
 
137
 
 
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);
 
142
 
 
143
    matrix.translate(data.rotation->xRotationPoint,
 
144
                     data.rotation->yRotationPoint,
 
145
                     data.rotation->zRotationPoint);
 
146
 
 
147
    matrix.rotate(data.rotation->angle, xAxis, yAxis, zAxis);
 
148
 
 
149
    matrix.translate(-data.rotation->xRotationPoint,
 
150
                     -data.rotation->yRotationPoint,
 
151
                     -data.rotation->zRotationPoint);
 
152
 
 
153
    return matrix;
 
154
}
 
155
 
 
156
void SceneOpenGL::paintGenericScreen(int mask, ScreenPaintData data)
 
157
{
 
158
    ShaderManager *shaderManager = ShaderManager::instance();
 
159
    const bool useShader = shaderManager->isValid();
 
160
    const QMatrix4x4 matrix = transformation(mask, data);
 
161
 
 
162
    if (useShader) {
 
163
        GLShader *shader = shaderManager->pushShader(ShaderManager::GenericShader);
 
164
        shader->setUniform(GLShader::ScreenTransformation, matrix);
 
165
    } else {
 
166
        pushMatrix(matrix);
 
167
    }
 
168
 
 
169
    Scene::paintGenericScreen(mask, data);
 
170
 
 
171
    if (useShader)
 
172
        shaderManager->popShader();
 
173
    else
 
174
        popMatrix();
 
175
}
 
176
 
 
177
void SceneOpenGL::paintBackground(QRegion region)
 
178
{
 
179
    PaintClipper pc(region);
 
180
    if (!PaintClipper::clip()) {
 
181
        glClearColor(0, 0, 0, 1);
 
182
        glClear(GL_COLOR_BUFFER_BIT);
 
183
        return;
 
184
    }
 
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();
 
196
    }
 
197
    GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
 
198
    vbo->reset();
 
199
    vbo->setUseColor(true);
 
200
    vbo->setData(verts.count() / 2, 2, verts.data(), NULL);
 
201
    const bool useShader = ShaderManager::instance()->isValid();
 
202
    if (useShader) {
 
203
        GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::ColorShader);
 
204
        shader->setUniform(GLShader::Offset, QVector2D(0, 0));
 
205
    }
 
206
    vbo->render(GL_TRIANGLES);
 
207
    if (useShader) {
 
208
        ShaderManager::instance()->popShader();
 
209
    }
 
210
}
 
211
 
 
212
void SceneOpenGL::windowAdded(Toplevel* c)
 
213
{
 
214
    assert(!windows.contains(c));
 
215
    windows[ c ] = new Window(c);
 
216
    c->effectWindow()->setSceneWindow(windows[ c ]);
 
217
    c->getShadow();
 
218
    windows[ c ]->updateShadow(c->shadow());
 
219
}
 
220
 
 
221
void SceneOpenGL::windowClosed(Toplevel* c, Deleted* deleted)
 
222
{
 
223
    assert(windows.contains(c));
 
224
    if (deleted != NULL) {
 
225
        // replace c with deleted
 
226
        Window* w = windows.take(c);
 
227
        w->updateToplevel(deleted);
 
228
        if (w->shadow()) {
 
229
            w->shadow()->setToplevel(deleted);
 
230
        }
 
231
        windows[ deleted ] = w;
 
232
    } else {
 
233
        delete windows.take(c);
 
234
        c->effectWindow()->setSceneWindow(NULL);
 
235
    }
 
236
}
 
237
 
 
238
void SceneOpenGL::windowDeleted(Deleted* c)
 
239
{
 
240
    assert(windows.contains(c));
 
241
    delete windows.take(c);
 
242
    c->effectWindow()->setSceneWindow(NULL);
 
243
}
 
244
 
 
245
void SceneOpenGL::windowGeometryShapeChanged(Toplevel* c)
 
246
{
 
247
    if (!windows.contains(c))    // this is ok, shape is not valid
 
248
        return;                 // by default
 
249
    Window* w = windows[ c ];
 
250
    w->discardShape();
 
251
    w->checkTextureSize();
 
252
}
 
253
 
 
254
void SceneOpenGL::windowOpacityChanged(Toplevel*)
 
255
{
 
256
#if 0 // not really needed, windows are painted on every repaint
 
257
    // and opacity is used when applying texture, not when
 
258
    // creating it
 
259
    if (!windows.contains(c))    // this is ok, texture is created
 
260
        return;                 // on demand
 
261
    Window* w = windows[ c ];
 
262
    w->discardTexture();
 
263
#endif
 
264
}
 
265
 
 
266
//****************************************
 
267
// SceneOpenGL::Texture
 
268
//****************************************
 
269
 
 
270
SceneOpenGL::Texture::Texture() : GLTexture()
 
271
{
 
272
    init();
 
273
}
 
274
 
 
275
SceneOpenGL::Texture::Texture(const Pixmap& pix, const QSize& size, int depth) : GLTexture()
 
276
{
 
277
    init();
 
278
    load(pix, size, depth);
 
279
}
 
280
 
 
281
SceneOpenGL::Texture::Texture(const QPixmap& pix, GLenum target)
 
282
    : GLTexture()
 
283
{
 
284
    init();
 
285
    load(pix, target);
 
286
}
 
287
 
 
288
SceneOpenGL::Texture::~Texture()
 
289
{
 
290
    discard();
 
291
}
 
292
 
 
293
void SceneOpenGL::Texture::createTexture()
 
294
{
 
295
    glGenTextures(1, &mTexture);
 
296
}
 
297
 
 
298
void SceneOpenGL::Texture::discard()
 
299
{
 
300
    if (mTexture != None)
 
301
        release();
 
302
    GLTexture::discard();
 
303
}
 
304
 
 
305
QRegion SceneOpenGL::Texture::optimizeBindDamage(const QRegion& reg, int limit)
 
306
{
 
307
    if (reg.rects().count() <= 1)
 
308
        return reg;
 
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
 
313
    int size = 0;
 
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();
 
318
    return reg;
 
319
}
 
320
 
 
321
bool SceneOpenGL::Texture::load(const Pixmap& pix, const QSize& size,
 
322
                                int depth)
 
323
{
 
324
    if (pix == None)
 
325
        return false;
 
326
    return load(pix, size, depth,
 
327
                QRegion(0, 0, size.width(), size.height()));
 
328
}
 
329
 
 
330
bool SceneOpenGL::Texture::load(const QImage& image, GLenum target)
 
331
{
 
332
    if (image.isNull())
 
333
        return false;
 
334
    return load(QPixmap::fromImage(image), target);
 
335
}
 
336
 
 
337
bool SceneOpenGL::Texture::load(const QPixmap& pixmap, GLenum target)
 
338
{
 
339
    if (pixmap.isNull())
 
340
        return false;
 
341
 
 
342
    // Checking whether QPixmap comes with its own X11 Pixmap
 
343
    if (Extensions::nonNativePixmaps()) {
 
344
        return GLTexture::load(pixmap.toImage(), target);
 
345
    }
 
346
 
 
347
    y_inverted = true;
 
348
 
 
349
    // use the X11 pixmap provided by Qt
 
350
    return load(pixmap.handle(), pixmap.size(), pixmap.depth());
 
351
}
 
352
 
 
353
//****************************************
 
354
// SceneOpenGL::Window
 
355
//****************************************
 
356
 
 
357
SceneOpenGL::Window::Window(Toplevel* c)
 
358
    : Scene::Window(c)
 
359
    , texture()
 
360
    , topTexture()
 
361
    , leftTexture()
 
362
    , rightTexture()
 
363
    , bottomTexture()
 
364
{
 
365
}
 
366
 
 
367
SceneOpenGL::Window::~Window()
 
368
{
 
369
    discardTexture();
 
370
}
 
371
 
 
372
// Bind the window pixmap to an OpenGL texture.
 
373
bool SceneOpenGL::Window::bindTexture()
 
374
{
 
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());
 
379
        return true;
 
380
    }
 
381
#endif
 
382
    // Get the pixmap with the window contents
 
383
    Pixmap pix = toplevel->windowPixmap();
 
384
    if (pix == None)
 
385
        return false;
 
386
    bool success = texture.load(pix, toplevel->size(), toplevel->depth(),
 
387
                                toplevel->damage());
 
388
    if (success)
 
389
        toplevel->resetDamage(QRect(toplevel->clientPos(), toplevel->clientSize()));
 
390
    else
 
391
        kDebug(1212) << "Failed to bind window";
 
392
    return success;
 
393
}
 
394
 
 
395
void SceneOpenGL::Window::discardTexture()
 
396
{
 
397
    texture.discard();
 
398
    topTexture.discard();
 
399
    leftTexture.discard();
 
400
    rightTexture.discard();
 
401
    bottomTexture.discard();
 
402
}
 
403
 
 
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()
 
411
{
 
412
    if (texture.size() != size())
 
413
        discardTexture();
 
414
}
 
415
 
 
416
// when the window's composite pixmap is discarded, undo binding it to the texture
 
417
void SceneOpenGL::Window::pixmapDiscarded()
 
418
{
 
419
    texture.release();
 
420
}
 
421
 
 
422
QMatrix4x4 SceneOpenGL::Window::transformation(int mask, const WindowPaintData &data) const
 
423
{
 
424
    QMatrix4x4 matrix;
 
425
    matrix.translate(x(), y());
 
426
 
 
427
    if (!(mask & PAINT_WINDOW_TRANSFORMED))
 
428
        return matrix;
 
429
 
 
430
    matrix.translate(data.xTranslate, data.yTranslate, data.zTranslate);
 
431
    matrix.scale(data.xScale, data.yScale, data.zScale);
 
432
 
 
433
    if (!data.rotation)
 
434
        return matrix;
 
435
 
 
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);
 
440
 
 
441
    matrix.translate(data.rotation->xRotationPoint,
 
442
                     data.rotation->yRotationPoint,
 
443
                     data.rotation->zRotationPoint);
 
444
 
 
445
    matrix.rotate(data.rotation->angle, xAxis, yAxis, zAxis);
 
446
 
 
447
    matrix.translate(-data.rotation->xRotationPoint,
 
448
                     -data.rotation->yRotationPoint,
 
449
                     -data.rotation->zRotationPoint);
 
450
 
 
451
    return matrix;
 
452
}
 
453
 
 
454
// paint the window
 
455
void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData data)
 
456
{
 
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
 
467
        }*/
 
468
 
 
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();
 
472
 
 
473
    if (region.isEmpty())
 
474
        return;
 
475
 
 
476
    if (!bindTexture())
 
477
        return;
 
478
 
 
479
    // Update the texture filter
 
480
    if (options->glSmoothScale != 0 &&
 
481
        (mask & (PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED)))
 
482
        filter = ImageFilterGood;
 
483
    else
 
484
        filter = ImageFilterFast;
 
485
 
 
486
    texture.setFilter(filter == ImageFilterGood ? GL_LINEAR : GL_NEAREST);
 
487
 
 
488
    bool sceneShader = false;
 
489
 
 
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);
 
494
        } else {
 
495
            data.shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader);
 
496
            data.shader->setUniform(GLShader::Offset, QVector2D(x(), y()));
 
497
        }
 
498
        sceneShader = true;
 
499
    }
 
500
 
 
501
    const QMatrix4x4 windowTransformation = transformation(mask, data);
 
502
 
 
503
    if (data.shader)
 
504
        data.shader->setUniform(GLShader::WindowTransformation, windowTransformation);
 
505
 
 
506
    if (!sceneShader)
 
507
        pushMatrix(windowTransformation);
 
508
 
 
509
    WindowQuadList decoration = data.quads.select(WindowQuadDecoration);
 
510
 
 
511
    GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
 
512
    vbo->reset();
 
513
 
 
514
    // shadow
 
515
    if (m_shadow) {
 
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);
 
524
    }
 
525
    // decorations
 
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()) {
 
537
            noBorder = false;
 
538
            updateDeco = client->decorationPixmapRequiresRepaint();
 
539
            client->ensureDecorationPixmapsPainted();
 
540
 
 
541
            client->layoutDecorationRects(leftRect, topRect, rightRect, bottomRect, Client::WindowRelative);
 
542
 
 
543
            left   = client->leftDecoPixmap();
 
544
            top    = client->topDecoPixmap();
 
545
            right  = client->rightDecoPixmap();
 
546
            bottom = client->bottomDecoPixmap();
 
547
        }
 
548
        if (deleted && !deleted->noBorder()) {
 
549
            noBorder = false;
 
550
            left   = deleted->leftDecoPixmap();
 
551
            top    = deleted->topDecoPixmap();
 
552
            right  = deleted->rightDecoPixmap();
 
553
            bottom = deleted->bottomDecoPixmap();
 
554
            deleted->layoutDecorationRects(leftRect, topRect, rightRect, bottomRect);
 
555
        }
 
556
        if (!noBorder) {
 
557
            WindowQuadList topList, leftList, rightList, bottomList;
 
558
 
 
559
            foreach (const WindowQuad & quad, decoration) {
 
560
                if (topRect.contains(QPoint(quad.originalLeft(), quad.originalTop()))) {
 
561
                    topList.append(quad);
 
562
                    continue;
 
563
                }
 
564
                if (bottomRect.contains(QPoint(quad.originalLeft(), quad.originalTop()))) {
 
565
                    bottomList.append(quad);
 
566
                    continue;
 
567
                }
 
568
                if (leftRect.contains(QPoint(quad.originalLeft(), quad.originalTop()))) {
 
569
                    leftList.append(quad);
 
570
                    continue;
 
571
                }
 
572
                if (rightRect.contains(QPoint(quad.originalLeft(), quad.originalTop()))) {
 
573
                    rightList.append(quad);
 
574
                    continue;
 
575
                }
 
576
            }
 
577
 
 
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);
 
582
        }
 
583
    }
 
584
 
 
585
    // paint the content
 
586
    if (!(mask & PAINT_DECORATION_ONLY)) {
 
587
        texture.bind();
 
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);
 
591
        texture.unbind();
 
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);
 
597
        }
 
598
#endif
 
599
    }
 
600
 
 
601
    if (sceneShader) {
 
602
        ShaderManager::instance()->popShader();
 
603
        data.shader = NULL;
 
604
    } else {
 
605
        popMatrix();
 
606
    }
 
607
}
 
608
 
 
609
void SceneOpenGL::Window::paintDecoration(const QPixmap* decoration, TextureType decorationType, const QRegion& region, const QRect& rect, const WindowPaintData& data, const WindowQuadList& quads, bool updateDeco)
 
610
{
 
611
    if (quads.isEmpty())
 
612
        return;
 
613
    SceneOpenGL::Texture* decorationTexture;
 
614
    switch(decorationType) {
 
615
    case DecorationTop:
 
616
        decorationTexture = &topTexture;
 
617
        break;
 
618
    case DecorationLeft:
 
619
        decorationTexture = &leftTexture;
 
620
        break;
 
621
    case DecorationRight:
 
622
        decorationTexture = &rightTexture;
 
623
        break;
 
624
    case DecorationBottom:
 
625
        decorationTexture = &bottomTexture;
 
626
        break;
 
627
    default:
 
628
        return;
 
629
    }
 
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);
 
635
        if (!success) {
 
636
            kDebug(1212) << "Failed to bind decoartion";
 
637
            return;
 
638
        }
 
639
    } else
 
640
        return;
 
641
    if (filter == ImageFilterGood)
 
642
        decorationTexture->setFilter(GL_LINEAR);
 
643
    else
 
644
        decorationTexture->setFilter(GL_NEAREST);
 
645
    decorationTexture->setWrapMode(GL_CLAMP_TO_EDGE);
 
646
    decorationTexture->bind();
 
647
 
 
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);
 
658
    }
 
659
#endif
 
660
}
 
661
 
 
662
void SceneOpenGL::Window::paintShadow(WindowQuadType type, const QRegion &region, const WindowPaintData &data)
 
663
{
 
664
    WindowQuadList quads = data.quads.select(type);
 
665
    Texture *texture = static_cast<SceneOpenGLShadow*>(m_shadow)->textureForQuadType(type);
 
666
    if (!texture) {
 
667
        return;
 
668
    }
 
669
    if (filter == ImageFilterGood)
 
670
        texture->setFilter(GL_LINEAR);
 
671
    else
 
672
        texture->setFilter(GL_NEAREST);
 
673
    texture->setWrapMode(GL_CLAMP_TO_EDGE);
 
674
    texture->bind();
 
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);
 
678
    texture->unbind();
 
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);
 
684
    }
 
685
#endif
 
686
}
 
687
 
 
688
void SceneOpenGL::Window::makeDecorationArrays(const WindowQuadList& quads, const QRect& rect, bool y_inverted) const
 
689
{
 
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();
 
709
 
 
710
        if (y_inverted) {
 
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;
 
723
        } else {
 
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;
 
736
        }
 
737
    }
 
738
    GLVertexBuffer::streamingBuffer()->setData(quads.count() * 6, 2, vertices.data(), texcoords.data());
 
739
}
 
740
 
 
741
void SceneOpenGL::Window::renderQuads(int, const QRegion& region, const WindowQuadList& quads, const QSizeF &size, bool yInverted)
 
742
{
 
743
    if (quads.isEmpty())
 
744
        return;
 
745
    // Render geometry
 
746
    float* vertices;
 
747
    float* texcoords;
 
748
    quads.makeArrays(&vertices, &texcoords, size, yInverted);
 
749
    GLVertexBuffer::streamingBuffer()->setData(quads.count() * 6, 2, vertices, texcoords);
 
750
    GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES);
 
751
    delete[] vertices;
 
752
    delete[] texcoords;
 
753
}
 
754
 
 
755
void SceneOpenGL::Window::prepareStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader)
 
756
{
 
757
    if (shader)
 
758
        prepareShaderRenderStates(type, opacity, brightness, saturation, shader);
 
759
    else {
 
760
        Texture *tex = NULL;
 
761
        switch(type) {
 
762
        case Content:
 
763
            tex = &texture;
 
764
            break;
 
765
        case DecorationTop:
 
766
            tex = &topTexture;
 
767
            break;
 
768
        case DecorationLeft:
 
769
            tex = &leftTexture;
 
770
            break;
 
771
        case DecorationRight:
 
772
            tex = &rightTexture;
 
773
            break;
 
774
        case DecorationBottom:
 
775
            tex = &bottomTexture;
 
776
            break;
 
777
        default:
 
778
            return;
 
779
        }
 
780
        prepareStates(type, opacity, brightness, saturation, shader, tex);
 
781
    }
 
782
}
 
783
 
 
784
void SceneOpenGL::Window::prepareStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader, Texture *texture)
 
785
{
 
786
    if (shader) {
 
787
        prepareShaderRenderStates(type, opacity, brightness, saturation, shader);
 
788
    } else {
 
789
        prepareRenderStates(type, opacity, brightness, saturation, texture);
 
790
    }
 
791
}
 
792
 
 
793
void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader)
 
794
{
 
795
    // setup blending of transparent windows
 
796
#ifndef KWIN_HAVE_OPENGLES
 
797
    glPushAttrib(GL_ENABLE_BIT);
 
798
#endif
 
799
    bool opaque = isOpaque() && opacity == 1.0;
 
800
    bool alpha = toplevel->hasAlpha() || type != Content;
 
801
    if (type != Content)
 
802
        opaque = false;
 
803
    if (!opaque) {
 
804
        glEnable(GL_BLEND);
 
805
        if (alpha) {
 
806
            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
807
        } else {
 
808
            glBlendColor((float)opacity, (float)opacity, (float)opacity, (float)opacity);
 
809
            glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_ALPHA);
 
810
        }
 
811
    }
 
812
 
 
813
    const float rgb = brightness * opacity;
 
814
    const float a = opacity;
 
815
 
 
816
    shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a));
 
817
    shader->setUniform(GLShader::Saturation,         saturation);
 
818
    shader->setUniform(GLShader::AlphaToOne,         opaque ? 1 : 0);
 
819
}
 
820
 
 
821
void SceneOpenGL::Window::prepareRenderStates(TextureType type, double opacity, double brightness, double saturation, Texture *tex)
 
822
{
 
823
#ifdef KWIN_HAVE_OPENGLES
 
824
    Q_UNUSED(type)
 
825
    Q_UNUSED(opacity)
 
826
    Q_UNUSED(brightness)
 
827
    Q_UNUSED(saturation)
 
828
    Q_UNUSED(tex)
 
829
#else
 
830
    bool alpha = false;
 
831
    bool opaque = true;
 
832
    if (type == Content) {
 
833
        alpha = toplevel->hasAlpha();
 
834
        opaque = isOpaque() && opacity == 1.0;
 
835
    } else {
 
836
        alpha = true;
 
837
        opaque = false;
 
838
    }
 
839
    // setup blending of transparent windows
 
840
    glPushAttrib(GL_ENABLE_BIT);
 
841
    if (!opaque) {
 
842
        glEnable(GL_BLEND);
 
843
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
844
    }
 
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);
 
858
        tex->bind();
 
859
 
 
860
        // Then we take dot product of the result of previous pass and
 
861
        //  saturation_constant. This gives us completely unsaturated
 
862
        //  (greyscale) image
 
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);
 
874
        tex->bind();
 
875
 
 
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);
 
894
        tex->bind();
 
895
 
 
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);
 
907
            if (alpha) {
 
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);
 
914
            } else {
 
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);
 
919
            }
 
920
            tex->bind();
 
921
        }
 
922
 
 
923
        glActiveTexture(GL_TEXTURE0);
 
924
    } else if (opacity != 1.0 || brightness != 1.0) {
 
925
        // the window is additionally configured to have its opacity adjusted,
 
926
        // do it
 
927
        float opacityByBrightness = opacity * brightness;
 
928
        if (alpha) {
 
929
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
930
            glColor4f(opacityByBrightness, opacityByBrightness, opacityByBrightness,
 
931
                      opacity);
 
932
        } else {
 
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);
 
944
        }
 
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);
 
953
    }
 
954
#endif
 
955
}
 
956
 
 
957
void SceneOpenGL::Window::restoreStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader)
 
958
{
 
959
    if (shader)
 
960
        restoreShaderRenderStates(type, opacity, brightness, saturation, shader);
 
961
    else {
 
962
        Texture *tex = NULL;
 
963
        switch(type) {
 
964
        case Content:
 
965
            tex = &texture;
 
966
            break;
 
967
        case DecorationTop:
 
968
            tex = &topTexture;
 
969
            break;
 
970
        case DecorationLeft:
 
971
            tex = &leftTexture;
 
972
            break;
 
973
        case DecorationRight:
 
974
            tex = &rightTexture;
 
975
            break;
 
976
        case DecorationBottom:
 
977
            tex = &bottomTexture;
 
978
            break;
 
979
        default:
 
980
            return;
 
981
        }
 
982
        restoreStates(type, opacity, brightness, saturation, shader, tex);
 
983
    }
 
984
}
 
985
 
 
986
void SceneOpenGL::Window::restoreStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader, Texture *texture)
 
987
{
 
988
    if (shader) {
 
989
        restoreShaderRenderStates(type, opacity, brightness, saturation, shader);
 
990
    } else {
 
991
        restoreRenderStates(type, opacity, brightness, saturation, texture);
 
992
    }
 
993
}
 
994
 
 
995
void SceneOpenGL::Window::restoreShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader)
 
996
{
 
997
    Q_UNUSED(brightness);
 
998
    Q_UNUSED(saturation);
 
999
    Q_UNUSED(shader);
 
1000
    bool opaque = isOpaque() && opacity == 1.0;
 
1001
    if (type != Content)
 
1002
        opaque = false;
 
1003
    if (!opaque) {
 
1004
        glDisable(GL_BLEND);
 
1005
    }
 
1006
    ShaderManager::instance()->getBoundShader()->setUniform(GLShader::AlphaToOne, 0);
 
1007
#ifndef KWIN_HAVE_OPENGLES
 
1008
    glPopAttrib();  // ENABLE_BIT
 
1009
#endif
 
1010
}
 
1011
 
 
1012
void SceneOpenGL::Window::restoreRenderStates(TextureType type, double opacity, double brightness, double saturation, Texture *tex)
 
1013
{
 
1014
    Q_UNUSED(type)
 
1015
#ifdef KWIN_HAVE_OPENGLES
 
1016
    Q_UNUSED(opacity)
 
1017
    Q_UNUSED(brightness)
 
1018
    Q_UNUSED(saturation)
 
1019
    Q_UNUSED(tex)
 
1020
#else
 
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);
 
1030
        }
 
1031
    }
 
1032
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
1033
    glColor4f(0, 0, 0, 0);
 
1034
 
 
1035
    glPopAttrib();  // ENABLE_BIT
 
1036
#endif
 
1037
}
 
1038
 
 
1039
//****************************************
 
1040
// SceneOpenGL::EffectFrame
 
1041
//****************************************
 
1042
 
 
1043
SceneOpenGL::Texture* SceneOpenGL::EffectFrame::m_unstyledTexture = NULL;
 
1044
QPixmap* SceneOpenGL::EffectFrame::m_unstyledPixmap = NULL;
 
1045
 
 
1046
SceneOpenGL::EffectFrame::EffectFrame(EffectFrameImpl* frame)
 
1047
    : Scene::EffectFrame(frame)
 
1048
    , m_texture(NULL)
 
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)
 
1056
{
 
1057
    if (m_effectFrame->style() == EffectFrameUnstyled && !m_unstyledTexture) {
 
1058
        updateUnstyledTexture();
 
1059
    }
 
1060
}
 
1061
 
 
1062
SceneOpenGL::EffectFrame::~EffectFrame()
 
1063
{
 
1064
    delete m_texture;
 
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;
 
1072
}
 
1073
 
 
1074
void SceneOpenGL::EffectFrame::free()
 
1075
{
 
1076
    glFlush();
 
1077
    delete m_texture;
 
1078
    m_texture = NULL;
 
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;
 
1093
}
 
1094
 
 
1095
void SceneOpenGL::EffectFrame::freeIconFrame()
 
1096
{
 
1097
    delete m_iconTexture;
 
1098
    m_iconTexture = NULL;
 
1099
}
 
1100
 
 
1101
void SceneOpenGL::EffectFrame::freeTextFrame()
 
1102
{
 
1103
    delete m_textTexture;
 
1104
    m_textTexture = NULL;
 
1105
    delete m_textPixmap;
 
1106
    m_textPixmap = NULL;
 
1107
}
 
1108
 
 
1109
void SceneOpenGL::EffectFrame::freeSelection()
 
1110
{
 
1111
    delete m_selectionTexture;
 
1112
    m_selectionTexture = NULL;
 
1113
}
 
1114
 
 
1115
void SceneOpenGL::EffectFrame::crossFadeIcon()
 
1116
{
 
1117
    delete m_oldIconTexture;
 
1118
    m_oldIconTexture = m_iconTexture;
 
1119
    m_iconTexture = NULL;
 
1120
}
 
1121
 
 
1122
void SceneOpenGL::EffectFrame::crossFadeText()
 
1123
{
 
1124
    delete m_oldTextTexture;
 
1125
    m_oldTextTexture = m_textTexture;
 
1126
    m_textTexture = NULL;
 
1127
}
 
1128
 
 
1129
void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double frameOpacity)
 
1130
{
 
1131
    if (m_effectFrame->geometry().isEmpty())
 
1132
        return; // Nothing to display
 
1133
 
 
1134
    region = infiniteRegion(); // TODO: Old region doesn't seem to work with OpenGL
 
1135
 
 
1136
    GLShader* shader = m_effectFrame->shader();
 
1137
    bool sceneShader = false;
 
1138
    if (!shader && ShaderManager::instance()->isValid()) {
 
1139
        shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader);
 
1140
        sceneShader = true;
 
1141
    } else if (shader) {
 
1142
        ShaderManager::instance()->pushShader(shader);
 
1143
    }
 
1144
 
 
1145
    if (shader) {
 
1146
        if (sceneShader)
 
1147
            shader->setUniform(GLShader::Offset, QVector2D(0, 0));
 
1148
 
 
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);
 
1152
    }
 
1153
 
 
1154
#ifndef KWIN_HAVE_OPENGLES
 
1155
    glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT);
 
1156
#endif
 
1157
    glEnable(GL_BLEND);
 
1158
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
1159
#ifndef KWIN_HAVE_OPENGLES
 
1160
    if (!shader)
 
1161
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
1162
 
 
1163
    // TODO: drop the push matrix
 
1164
    glPushMatrix();
 
1165
#endif
 
1166
 
 
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();
 
1172
            area.moveTo(0, 0);
 
1173
            area.adjust(-5, -5, 5, 5);
 
1174
 
 
1175
            const int roundness = 5;
 
1176
            QVector<float> verts, texCoords;
 
1177
            verts.reserve(84);
 
1178
            texCoords.reserve(84);
 
1179
 
 
1180
            // top left
 
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;
 
1193
            // top
 
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;
 
1206
            // top right
 
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;
 
1219
            // bottom left
 
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;
 
1232
            // bottom
 
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;
 
1245
            // bottom right
 
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;
 
1258
            // center
 
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;
 
1271
 
 
1272
            m_unstyledVBO->setData(verts.count() / 2, 2, verts.data(), texCoords.data());
 
1273
        }
 
1274
 
 
1275
        if (shader) {
 
1276
            const float a = opacity * frameOpacity;
 
1277
            shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
 
1278
        }
 
1279
#ifndef KWIN_HAVE_OPENGLES
 
1280
        else
 
1281
            glColor4f(0.0, 0.0, 0.0, opacity * frameOpacity);
 
1282
#endif
 
1283
 
 
1284
        m_unstyledTexture->bind();
 
1285
        const QPoint pt = m_effectFrame->geometry().topLeft();
 
1286
        if (sceneShader) {
 
1287
            shader->setUniform(GLShader::Offset, QVector2D(pt.x(), pt.y()));
 
1288
        } else {
 
1289
            QMatrix4x4 translation;
 
1290
            translation.translate(pt.x(), pt.y());
 
1291
            if (shader) {
 
1292
                shader->setUniform(GLShader::WindowTransformation, translation);
 
1293
            } else {
 
1294
                pushMatrix(translation);
 
1295
            }
 
1296
        }
 
1297
        m_unstyledVBO->render(region, GL_TRIANGLES);
 
1298
        if (!sceneShader) {
 
1299
            if (shader) {
 
1300
                shader->setUniform(GLShader::WindowTransformation, QMatrix4x4());
 
1301
            } else {
 
1302
                popMatrix();
 
1303
            }
 
1304
        }
 
1305
        m_unstyledTexture->unbind();
 
1306
    } else if (m_effectFrame->style() == EffectFrameStyled) {
 
1307
        if (!m_texture)   // Lazy creation
 
1308
            updateTexture();
 
1309
 
 
1310
        if (shader) {
 
1311
            const float a = opacity * frameOpacity;
 
1312
            shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
 
1313
        }
 
1314
#ifndef KWIN_HAVE_OPENGLES
 
1315
        else
 
1316
            glColor4f(1.0, 1.0, 1.0, opacity * frameOpacity);
 
1317
#endif
 
1318
        m_texture->bind();
 
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();
 
1323
 
 
1324
    }
 
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);
 
1330
        }
 
1331
        if (m_selectionTexture) {
 
1332
            if (shader) {
 
1333
                const float a = opacity * frameOpacity;
 
1334
                shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
 
1335
            }
 
1336
    #ifndef KWIN_HAVE_OPENGLES
 
1337
            else
 
1338
                glColor4f(1.0, 1.0, 1.0, opacity * frameOpacity);
 
1339
    #endif
 
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);
 
1345
        }
 
1346
    }
 
1347
 
 
1348
    // Render icon
 
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);
 
1352
 
 
1353
        if (m_effectFrame->isCrossFade() && m_oldIconTexture) {
 
1354
            if (shader) {
 
1355
                const float a = opacity * (1.0 - m_effectFrame->crossFadeProgress());
 
1356
                shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
 
1357
            }
 
1358
#ifndef KWIN_HAVE_OPENGLES
 
1359
            else
 
1360
                glColor4f(1.0, 1.0, 1.0, opacity * (1.0 - m_effectFrame->crossFadeProgress()));
 
1361
#endif
 
1362
 
 
1363
            m_oldIconTexture->bind();
 
1364
            m_oldIconTexture->render(region, QRect(topLeft, m_effectFrame->iconSize()));
 
1365
            m_oldIconTexture->unbind();
 
1366
            if (shader) {
 
1367
                const float a = opacity * m_effectFrame->crossFadeProgress();
 
1368
                shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
 
1369
            }
 
1370
#ifndef KWIN_HAVE_OPENGLES
 
1371
            else
 
1372
                glColor4f(1.0, 1.0, 1.0, opacity * m_effectFrame->crossFadeProgress());
 
1373
#endif
 
1374
        } else {
 
1375
            if (shader) {
 
1376
                const QVector4D constant(opacity, opacity, opacity, opacity);
 
1377
                shader->setUniform(GLShader::ModulationConstant, constant);
 
1378
            }
 
1379
#ifndef KWIN_HAVE_OPENGLES
 
1380
            else
 
1381
                glColor4f(1.0, 1.0, 1.0, opacity);
 
1382
#endif
 
1383
        }
 
1384
 
 
1385
        if (!m_iconTexture) { // lazy creation
 
1386
            m_iconTexture = new Texture(m_effectFrame->icon());
 
1387
        }
 
1388
        m_iconTexture->bind();
 
1389
        m_iconTexture->render(region, QRect(topLeft, m_effectFrame->iconSize()));
 
1390
        m_iconTexture->unbind();
 
1391
    }
 
1392
 
 
1393
    // Render text
 
1394
    if (!m_effectFrame->text().isEmpty()) {
 
1395
        if (m_effectFrame->isCrossFade() && m_oldTextTexture) {
 
1396
            if (shader) {
 
1397
                const float a = opacity * (1.0 - m_effectFrame->crossFadeProgress());
 
1398
                shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
 
1399
            }
 
1400
#ifndef KWIN_HAVE_OPENGLES
 
1401
            else
 
1402
                glColor4f(1.0, 1.0, 1.0, opacity *(1.0 - m_effectFrame->crossFadeProgress()));
 
1403
#endif
 
1404
 
 
1405
            m_oldTextTexture->bind();
 
1406
            m_oldTextTexture->render(region, m_effectFrame->geometry());
 
1407
            m_oldTextTexture->unbind();
 
1408
            if (shader) {
 
1409
                const float a = opacity * m_effectFrame->crossFadeProgress();
 
1410
                shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a));
 
1411
            }
 
1412
#ifndef KWIN_HAVE_OPENGLES
 
1413
            else
 
1414
                glColor4f(1.0, 1.0, 1.0, opacity * m_effectFrame->crossFadeProgress());
 
1415
#endif
 
1416
        } else {
 
1417
            if (shader) {
 
1418
                const QVector4D constant(opacity, opacity, opacity, opacity);
 
1419
                shader->setUniform(GLShader::ModulationConstant, constant);
 
1420
            }
 
1421
#ifndef KWIN_HAVE_OPENGLES
 
1422
            else
 
1423
                glColor4f(1.0, 1.0, 1.0, opacity);
 
1424
#endif
 
1425
        }
 
1426
        if (!m_textTexture)   // Lazy creation
 
1427
            updateTextTexture();
 
1428
        m_textTexture->bind();
 
1429
        m_textTexture->render(region, m_effectFrame->geometry());
 
1430
        m_textTexture->unbind();
 
1431
    }
 
1432
 
 
1433
    if (shader) {
 
1434
        ShaderManager::instance()->popShader();
 
1435
    }
 
1436
    glDisable(GL_BLEND);
 
1437
#ifndef KWIN_HAVE_OPENGLES
 
1438
    glPopMatrix();
 
1439
    glPopAttrib();
 
1440
#endif
 
1441
}
 
1442
 
 
1443
void SceneOpenGL::EffectFrame::updateTexture()
 
1444
{
 
1445
    delete m_texture;
 
1446
    m_texture = 0L;
 
1447
    if (m_effectFrame->style() == EffectFrameStyled) {
 
1448
        QPixmap pixmap = m_effectFrame->frame().framePixmap();
 
1449
        m_texture = new Texture(pixmap);
 
1450
    }
 
1451
}
 
1452
 
 
1453
void SceneOpenGL::EffectFrame::updateTextTexture()
 
1454
{
 
1455
    delete m_textTexture;
 
1456
    m_textTexture = 0L;
 
1457
    delete m_textPixmap;
 
1458
    m_textPixmap = 0L;
 
1459
 
 
1460
    if (m_effectFrame->text().isEmpty())
 
1461
        return;
 
1462
 
 
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());
 
1467
 
 
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());
 
1473
    }
 
1474
 
 
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);
 
1484
    p.end();
 
1485
    m_textTexture = new Texture(*m_textPixmap);
 
1486
}
 
1487
 
 
1488
void SceneOpenGL::EffectFrame::updateUnstyledTexture()
 
1489
{
 
1490
    delete m_unstyledTexture;
 
1491
    m_unstyledTexture = 0L;
 
1492
    delete m_unstyledPixmap;
 
1493
    m_unstyledPixmap = 0L;
 
1494
    // Based off circle() from kwinxrenderutils.cpp
 
1495
#define CS 8
 
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());
 
1503
    p.end();
 
1504
#undef CS
 
1505
    m_unstyledTexture = new Texture(*m_unstyledPixmap);
 
1506
}
 
1507
 
 
1508
void SceneOpenGL::EffectFrame::cleanup()
 
1509
{
 
1510
    delete m_unstyledTexture;
 
1511
    m_unstyledTexture = NULL;
 
1512
    delete m_unstyledPixmap;
 
1513
    m_unstyledPixmap = NULL;
 
1514
}
 
1515
 
 
1516
//****************************************
 
1517
// SceneOpenGL::Shadow
 
1518
//****************************************
 
1519
SceneOpenGLShadow::SceneOpenGLShadow(Toplevel *toplevel)
 
1520
    : Shadow(toplevel)
 
1521
{
 
1522
}
 
1523
 
 
1524
SceneOpenGLShadow::~SceneOpenGLShadow()
 
1525
{
 
1526
    for (int i=0; i<ShadowElementsCount; ++i) {
 
1527
        m_shadowTextures[i].discard();
 
1528
    }
 
1529
}
 
1530
 
 
1531
SceneOpenGL::Texture *SceneOpenGLShadow::textureForQuadType(WindowQuadType type)
 
1532
{
 
1533
    SceneOpenGL::Texture *texture = NULL;
 
1534
    QPixmap pixmap;
 
1535
    switch (type) {
 
1536
    case WindowQuadShadowTop:
 
1537
        texture = &m_shadowTextures[ShadowElementTop];
 
1538
        pixmap = shadowPixmap(ShadowElementTop);
 
1539
        break;
 
1540
    case WindowQuadShadowTopRight:
 
1541
        texture = &m_shadowTextures[ShadowElementTopRight];
 
1542
        pixmap = shadowPixmap(ShadowElementTopRight);
 
1543
        break;
 
1544
    case WindowQuadShadowRight:
 
1545
        texture = &m_shadowTextures[ShadowElementRight];
 
1546
        pixmap = shadowPixmap(ShadowElementRight);
 
1547
        break;
 
1548
    case WindowQuadShadowBottomRight:
 
1549
        texture = &m_shadowTextures[ShadowElementBottomRight];
 
1550
        pixmap = shadowPixmap(ShadowElementBottomRight);
 
1551
        break;
 
1552
    case WindowQuadShadowBottom:
 
1553
        texture = &m_shadowTextures[ShadowElementBottom];
 
1554
        pixmap = shadowPixmap(ShadowElementBottom);
 
1555
        break;
 
1556
    case WindowQuadShadowBottomLeft:
 
1557
        texture = &m_shadowTextures[ShadowElementBottomLeft];
 
1558
        pixmap = shadowPixmap(ShadowElementBottomLeft);
 
1559
        break;
 
1560
    case WindowQuadShadowLeft:
 
1561
        texture = &m_shadowTextures[ShadowElementLeft];
 
1562
        pixmap = shadowPixmap(ShadowElementLeft);
 
1563
        break;
 
1564
    case WindowQuadShadowTopLeft:
 
1565
        texture = &m_shadowTextures[ShadowElementTopLeft];
 
1566
        pixmap = shadowPixmap(ShadowElementTopLeft);
 
1567
        break;
 
1568
    default:
 
1569
        // nothing
 
1570
        break;
 
1571
    }
 
1572
    if (texture) {
 
1573
        if (texture->texture() != None) {
 
1574
            glBindTexture(texture->target(), texture->texture());
 
1575
        } else if (!pixmap.isNull()) {
 
1576
            const bool success = texture->load(pixmap);
 
1577
            if (!success) {
 
1578
                kDebug(1212) << "Failed to bind shadow pixmap";
 
1579
                return NULL;
 
1580
            }
 
1581
        } else {
 
1582
            return NULL;
 
1583
        }
 
1584
    }
 
1585
    return texture;
 
1586
}
 
1587
 
 
1588
} // namespace
 
1589
 
 
1590
#endif