~mc-return/compiz/compiz.merge-src-screen.cpp-improvements

« back to all changes in this revision

Viewing changes to plugins/blur.cpp

  • Committer: Dennis kasprzyk
  • Author(s): Dennis Kasprzyk
  • Date: 2009-03-15 05:09:18 UTC
  • Revision ID: git-v1:163f6b6f3c3b7764987cbdf8e03cc355edeaa499
New generalized build system.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2007 Novell, Inc.
3
 
 *
4
 
 * Permission to use, copy, modify, distribute, and sell this software
5
 
 * and its documentation for any purpose is hereby granted without
6
 
 * fee, provided that the above copyright notice appear in all copies
7
 
 * and that both that copyright notice and this permission notice
8
 
 * appear in supporting documentation, and that the name of
9
 
 * Novell, Inc. not be used in advertising or publicity pertaining to
10
 
 * distribution of the software without specific, written prior permission.
11
 
 * Novell, Inc. makes no representations about the suitability of this
12
 
 * software for any purpose. It is provided "as is" without express or
13
 
 * implied warranty.
14
 
 *
15
 
 * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
 
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
 
 * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
 
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
 
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
 
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
 
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
 
 *
23
 
 * Author: David Reveman <davidr@novell.com>
24
 
 */
25
 
 
26
 
#include <blur.h>
27
 
 
28
 
COMPIZ_PLUGIN_20081216 (blur, BlurPluginVTable)
29
 
 
30
 
/* pascal triangle based kernel generator */
31
 
static int
32
 
blurCreateGaussianLinearKernel (int   radius,
33
 
                                float strength,
34
 
                                float *amp,
35
 
                                float *pos,
36
 
                                int   *optSize)
37
 
{
38
 
    float factor = 0.5f + (strength / 2.0f);
39
 
    float buffer1[BLUR_GAUSSIAN_RADIUS_MAX * 3];
40
 
    float buffer2[BLUR_GAUSSIAN_RADIUS_MAX * 3];
41
 
    float *ar1 = buffer1;
42
 
    float *ar2 = buffer2;
43
 
    float *tmp;
44
 
    float sum = 0;
45
 
    int   size = (radius * 2) + 1;
46
 
    int   mySize = ceil (radius / 2.0f);
47
 
    int   i, j;
48
 
 
49
 
    ar1[0] = 1.0;
50
 
    ar1[1] = 1.0;
51
 
 
52
 
    for (i = 3; i <= size; i++)
53
 
    {
54
 
        ar2[0] = 1;
55
 
 
56
 
        for (j = 1; j < i - 1; j++)
57
 
            ar2[j] = (ar1[j - 1] + ar1[j]) * factor;
58
 
 
59
 
        ar2[i - 1] = 1;
60
 
 
61
 
        tmp = ar1;
62
 
        ar1 = ar2;
63
 
        ar2 = tmp;
64
 
    }
65
 
 
66
 
    /* normalize */
67
 
    for (i = 0; i < size; i++)
68
 
        sum += ar1[i];
69
 
 
70
 
    if (sum != 0.0f)
71
 
        sum = 1.0f / sum;
72
 
 
73
 
    for (i = 0; i < size; i++)
74
 
        ar1[i] *= sum;
75
 
 
76
 
    i = 0;
77
 
    j = 0;
78
 
 
79
 
    if (radius & 1)
80
 
    {
81
 
        pos[i] = radius;
82
 
        amp[i] = ar1[i];
83
 
        i = 1;
84
 
        j = 1;
85
 
    }
86
 
 
87
 
    for (; i < mySize; i++)
88
 
    {
89
 
        pos[i]  = radius - j;
90
 
        pos[i] -= ar1[j + 1] / (ar1[j] + ar1[j + 1]);
91
 
        amp[i]  = ar1[j] + ar1[j + 1];
92
 
 
93
 
        j += 2;
94
 
    }
95
 
 
96
 
    pos[mySize] = 0.0;
97
 
    amp[mySize] = ar1[radius];
98
 
 
99
 
    *optSize = mySize;
100
 
 
101
 
    return radius;
102
 
}
103
 
 
104
 
void
105
 
BlurScreen::updateFilterRadius ()
106
 
{
107
 
 
108
 
    switch (opt[BLUR_OPTION_FILTER].value ().i ()) {
109
 
        case BLUR_FILTER_4X_BILINEAR:
110
 
            filterRadius = 2;
111
 
            break;
112
 
        case BLUR_FILTER_GAUSSIAN: {
113
 
            int   radius   = opt[BLUR_OPTION_GAUSSIAN_RADIUS].value ().i ();
114
 
            float strength = opt[BLUR_OPTION_GAUSSIAN_STRENGTH].value ().f ();
115
 
 
116
 
            blurCreateGaussianLinearKernel (radius, strength, amp, pos,
117
 
                                            &numTexop);
118
 
 
119
 
            filterRadius = radius;
120
 
        } break;
121
 
        case BLUR_FILTER_MIPMAP: {
122
 
            float lod = opt[BLUR_OPTION_MIPMAP_LOD].value ().f ();
123
 
 
124
 
            filterRadius = powf (2.0f, ceilf (lod));
125
 
        } break;
126
 
    }
127
 
}
128
 
 
129
 
 
130
 
void
131
 
BlurScreen::blurReset ()
132
 
{
133
 
    updateFilterRadius ();
134
 
 
135
 
    foreach (BlurFunction &bf, srcBlurFunctions)
136
 
        GLFragment::destroyFragmentFunction (bf.id);
137
 
    srcBlurFunctions.clear ();
138
 
    foreach (BlurFunction &bf, dstBlurFunctions)
139
 
        GLFragment::destroyFragmentFunction (bf.id);
140
 
    dstBlurFunctions.clear ();
141
 
 
142
 
    width = height = 0;
143
 
 
144
 
    if (program)
145
 
    {
146
 
        GL::deletePrograms (1, &program);
147
 
        program = 0;
148
 
    }
149
 
}
150
 
 
151
 
static CompRegion
152
 
regionFromBoxes (std::vector<BlurBox> boxes,
153
 
                 int     width,
154
 
                 int     height)
155
 
{
156
 
    CompRegion region;
157
 
    int        x1, x2, y1, y2;
158
 
 
159
 
    foreach (BlurBox &box, boxes)
160
 
    {
161
 
        decor_apply_gravity (box.p1.gravity, box.p1.x, box.p1.y,
162
 
                             width, height,
163
 
                             &x1, &y1);
164
 
 
165
 
 
166
 
        decor_apply_gravity (box.p2.gravity, box.p2.x, box.p2.y,
167
 
                             width, height,
168
 
                             &x2, &y2);
169
 
 
170
 
        if (x2 > x1 && y2 > y1)
171
 
            region += CompRect (x1, y1, x2 - x1, y2 - y1);
172
 
    }
173
 
 
174
 
    return region;
175
 
}
176
 
 
177
 
void
178
 
BlurWindow::updateRegion ()
179
 
{
180
 
    CompRegion region;
181
 
 
182
 
    if (state[BLUR_STATE_DECOR].threshold)
183
 
    {
184
 
        region += CompRect (-window->output ().left,
185
 
                            -window->output ().top,
186
 
                            window->width () + window->output ().right,
187
 
                            window->height () + window->output ().bottom);
188
 
 
189
 
        region -= CompRect (0, 0, window->width (), window->height ());
190
 
 
191
 
        state[BLUR_STATE_DECOR].clipped = false;
192
 
 
193
 
        if (!state[BLUR_STATE_DECOR].box.empty ())
194
 
        {
195
 
            CompRegion q = regionFromBoxes (state[BLUR_STATE_DECOR].box,
196
 
                                            window->width (),
197
 
                                            window->height ());
198
 
            if (!q.isEmpty ())
199
 
            {
200
 
                q &= region;
201
 
                if (q != region)
202
 
                {
203
 
                    region = q;
204
 
                    state[BLUR_STATE_DECOR].clipped = true;
205
 
                }
206
 
            }
207
 
        }
208
 
    }
209
 
 
210
 
    if (state[BLUR_STATE_CLIENT].threshold)
211
 
    {
212
 
        CompRegion r (0, 0, window->width (), window->height ());
213
 
 
214
 
        state[BLUR_STATE_CLIENT].clipped = false;
215
 
 
216
 
        if (!state[BLUR_STATE_CLIENT].box.empty ())
217
 
        {
218
 
            CompRegion q = regionFromBoxes (state[BLUR_STATE_CLIENT].box,
219
 
                                            window->width (),
220
 
                                            window->height ());
221
 
            if (!q.isEmpty ())
222
 
            {
223
 
                q &= r;
224
 
                
225
 
                if (q != r)
226
 
                    state[BLUR_STATE_CLIENT].clipped = true;
227
 
 
228
 
                region += q;
229
 
            }
230
 
        }
231
 
        else
232
 
        {
233
 
            region += r;
234
 
        }
235
 
    }
236
 
 
237
 
    this->region = region;
238
 
    if (!region.isEmpty ())
239
 
        this->region.translate (window->x (), window->y ());
240
 
}
241
 
 
242
 
void
243
 
BlurWindow::setBlur (int                  state,
244
 
                     int                  threshold,
245
 
                     std::vector<BlurBox> box)
246
 
{
247
 
 
248
 
    this->state[state].threshold = threshold;
249
 
    this->state[state].box       = box;
250
 
 
251
 
    updateRegion ();
252
 
 
253
 
    cWindow->addDamage ();
254
 
}
255
 
 
256
 
void
257
 
BlurWindow::updateAlphaMatch ()
258
 
{
259
 
    if (!propSet[BLUR_STATE_CLIENT])
260
 
    {
261
 
        CompMatch *match;
262
 
 
263
 
        match = &bScreen->opt[BLUR_OPTION_ALPHA_BLUR_MATCH].value ().match ();
264
 
        if (match->evaluate (window))
265
 
        {
266
 
            if (!state[BLUR_STATE_CLIENT].threshold)
267
 
                setBlur (BLUR_STATE_CLIENT, 4, std::vector<BlurBox> ());
268
 
        }
269
 
        else
270
 
        {
271
 
            if (state[BLUR_STATE_CLIENT].threshold)
272
 
                setBlur (BLUR_STATE_CLIENT, 0, std::vector<BlurBox> ());
273
 
        }
274
 
    }
275
 
}
276
 
 
277
 
void
278
 
BlurWindow::updateMatch ()
279
 
{
280
 
    CompMatch *match;
281
 
    bool      focus;
282
 
 
283
 
    updateAlphaMatch ();
284
 
 
285
 
    match = &bScreen->opt[BLUR_OPTION_FOCUS_BLUR_MATCH].value ().match ();
286
 
 
287
 
    focus = GL::fragmentProgram && match->evaluate (window);
288
 
    if (focus != focusBlur)
289
 
    {
290
 
        focusBlur = focus;
291
 
        cWindow->addDamage ();
292
 
    }
293
 
}
294
 
 
295
 
 
296
 
 
297
 
void
298
 
BlurWindow::update (int state)
299
 
{
300
 
    Atom          actual;
301
 
    int           result, format;
302
 
    unsigned long n, left;
303
 
    unsigned char *propData;
304
 
    int           threshold = 0;
305
 
    std::vector<BlurBox> boxes;
306
 
 
307
 
    result = XGetWindowProperty (screen->dpy (), window->id (),
308
 
                                 bScreen->blurAtom[state], 0L, 8192L, FALSE,
309
 
                                 XA_INTEGER, &actual, &format,
310
 
                                 &n, &left, &propData);
311
 
 
312
 
    if (result == Success && n && propData)
313
 
    {
314
 
        propSet[state] = true;
315
 
 
316
 
        if (n >= 2)
317
 
        {
318
 
            long *data = (long *) propData;
319
 
            BlurBox box;
320
 
 
321
 
            threshold = data[0];
322
 
 
323
 
            if ((n - 2) / 6)
324
 
            {
325
 
                int i;
326
 
 
327
 
                data += 2;
328
 
 
329
 
                for (i = 0; i < (n - 2) / 6; i++)
330
 
                {
331
 
                    box.p1.gravity = *data++;
332
 
                    box.p1.x       = *data++;
333
 
                    box.p1.y       = *data++;
334
 
                    box.p2.gravity = *data++;
335
 
                    box.p2.x       = *data++;
336
 
                    box.p2.y       = *data++;
337
 
 
338
 
                    boxes.push_back (box);
339
 
                }
340
 
 
341
 
            }
342
 
        }
343
 
 
344
 
        XFree (propData);
345
 
    }
346
 
    else
347
 
    {
348
 
        propSet[state] = false;
349
 
    }
350
 
 
351
 
    setBlur (state, threshold, boxes);
352
 
 
353
 
    updateAlphaMatch ();
354
 
}
355
 
 
356
 
void
357
 
BlurScreen::preparePaint (int msSinceLastPaint)
358
 
{
359
 
    if (moreBlur)
360
 
    {
361
 
        int         steps;
362
 
        bool        focus = opt[BLUR_OPTION_FOCUS_BLUR].value ().b ();
363
 
        bool        focusBlur;
364
 
 
365
 
        steps = (msSinceLastPaint * 0xffff) / blurTime;
366
 
        if (steps < 12)
367
 
            steps = 12;
368
 
 
369
 
        moreBlur = false;
370
 
 
371
 
        foreach (CompWindow *w, screen->windows ())
372
 
        {
373
 
            BLUR_WINDOW (w);
374
 
 
375
 
            focusBlur = bw->focusBlur && focus;
376
 
 
377
 
            if (!bw->pulse &&
378
 
                (!focusBlur || w->id () == screen->activeWindow ()))
379
 
            {
380
 
                if (bw->blur)
381
 
                {
382
 
                    bw->blur -= steps;
383
 
                    if (bw->blur > 0)
384
 
                        moreBlur = true;
385
 
                    else
386
 
                        bw->blur = 0;
387
 
                }
388
 
            }
389
 
            else
390
 
            {
391
 
                if (bw->blur < 0xffff)
392
 
                {
393
 
                    if (bw->pulse)
394
 
                    {
395
 
                        bw->blur += steps * 2;
396
 
 
397
 
                        if (bw->blur >= 0xffff)
398
 
                        {
399
 
                            bw->blur = 0xffff - 1;
400
 
                            bw->pulse = false;
401
 
                        }
402
 
 
403
 
                        moreBlur = true;
404
 
                    }
405
 
                    else
406
 
                    {
407
 
                        bw->blur += steps;
408
 
                        if (bw->blur < 0xffff)
409
 
                            moreBlur = true;
410
 
                        else
411
 
                            bw->blur = 0xffff;
412
 
                    }
413
 
                }
414
 
            }
415
 
        }
416
 
    }
417
 
 
418
 
    cScreen->preparePaint (msSinceLastPaint);
419
 
 
420
 
    if (cScreen->damageMask () & COMPOSITE_SCREEN_DAMAGE_REGION_MASK)
421
 
    {
422
 
        /* walk from bottom to top and expand damage */
423
 
        if (alphaBlur)
424
 
        {
425
 
            int        x1, y1, x2, y2;
426
 
            int        count = 0;
427
 
            CompRegion damage (cScreen->currentDamage ());
428
 
 
429
 
            foreach (CompWindow *w, screen->windows ())
430
 
            {
431
 
                BLUR_WINDOW (w);
432
 
                
433
 
                if (!w->isViewable () || !CompositeWindow::get (w)->damaged ())
434
 
                    continue;
435
 
 
436
 
                if (!bw->region.isEmpty ())
437
 
                {
438
 
                    CompRect r = bw->region.boundingRect ();
439
 
                    CompRect d = damage.boundingRect ();
440
 
                    x1 = r.x1 () - filterRadius;
441
 
                    y1 = r.y1 () - filterRadius;
442
 
                    x2 = r.x2 () + filterRadius;
443
 
                    y2 = r.y2 () + filterRadius;
444
 
 
445
 
                    if (x1 < d.x2 () &&
446
 
                        y1 < d.y2 () &&
447
 
                        x2 > d.x1 () &&
448
 
                        y2 > d.y1 ())
449
 
                    {
450
 
                        damage.shrink (-filterRadius, -filterRadius);
451
 
                        count++;
452
 
                    }
453
 
                }
454
 
            }
455
 
 
456
 
            if (count)
457
 
                cScreen->damageRegion (damage);
458
 
 
459
 
            this->count = count;
460
 
        }
461
 
    }
462
 
}
463
 
 
464
 
bool
465
 
BlurScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib,
466
 
                           const GLMatrix &transform, const CompRegion &region,
467
 
                           CompOutput *output, unsigned int mask)
468
 
{
469
 
    bool status;
470
 
 
471
 
    if (alphaBlur)
472
 
    {
473
 
        stencilBox = region.boundingRect ();
474
 
        this->region = region;
475
 
 
476
 
        if (mask & PAINT_SCREEN_REGION_MASK)
477
 
        {
478
 
            /* we need to redraw more than the screen region being updated */
479
 
            if (count)
480
 
            {
481
 
                this->region.shrink (-filterRadius * 2, -filterRadius * 2);
482
 
 
483
 
                this->region &= screen->region ();
484
 
            }
485
 
        }
486
 
    }
487
 
 
488
 
    if (!blurOcclusion)
489
 
    {
490
 
        occlusion = CompRegion ();
491
 
 
492
 
        foreach (CompWindow *w, screen->windows ())
493
 
            BlurWindow::get (w)->clip = CompRegion ();
494
 
    }
495
 
 
496
 
    this->output = output;
497
 
 
498
 
    if (alphaBlur)
499
 
        status = gScreen->glPaintOutput (sAttrib, transform, this->region, output, mask);
500
 
    else
501
 
        status = gScreen->glPaintOutput (sAttrib, transform, region, output, mask);
502
 
 
503
 
    return status;
504
 
}
505
 
 
506
 
void
507
 
BlurScreen::glPaintTransformedOutput (const GLScreenPaintAttrib &sAttrib,
508
 
                                      const GLMatrix &transform,
509
 
                                      const CompRegion &region,
510
 
                                      CompOutput *output, unsigned int mask)
511
 
{
512
 
    if (!blurOcclusion)
513
 
    {
514
 
        occlusion = CompRegion ();
515
 
 
516
 
        foreach (CompWindow *w, screen->windows ())
517
 
            BlurWindow::get (w)->clip = CompRegion ();
518
 
    }
519
 
 
520
 
    gScreen->glPaintTransformedOutput (sAttrib, transform, region, output, mask);
521
 
}
522
 
 
523
 
void
524
 
BlurScreen::donePaint ()
525
 
{
526
 
    if (moreBlur)
527
 
    {
528
 
        foreach (CompWindow *w, screen->windows ())
529
 
        {
530
 
            BLUR_WINDOW (w);
531
 
 
532
 
            if (bw->blur > 0 && bw->blur < 0xffff)
533
 
                bw->cWindow->addDamage ();
534
 
        }
535
 
    }
536
 
 
537
 
    cScreen->donePaint ();
538
 
}
539
 
 
540
 
bool
541
 
BlurWindow::glPaint (const GLWindowPaintAttrib &attrib,
542
 
                     const GLMatrix &transform,
543
 
                     const CompRegion &region, unsigned int mask)
544
 
{
545
 
 
546
 
    bool status = gWindow->glPaint (attrib, transform, region, mask);
547
 
 
548
 
    if (!bScreen->blurOcclusion &&
549
 
        (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK))
550
 
    {
551
 
        clip = bScreen->occlusion;
552
 
 
553
 
        if (!(gWindow->lastMask () & PAINT_WINDOW_NO_CORE_INSTANCE_MASK) &&
554
 
            !(gWindow->lastMask () & PAINT_WINDOW_TRANSFORMED_MASK) &&
555
 
            !this->region.isEmpty ())
556
 
            bScreen->occlusion += this->region;
557
 
    }
558
 
 
559
 
    return status;
560
 
}
561
 
 
562
 
GLFragment::FunctionId
563
 
BlurScreen::getSrcBlurFragmentFunction (GLTexture *texture,
564
 
                                        int       param)
565
 
{
566
 
    GLFragment::FunctionData data;
567
 
    BlurFunction             function;
568
 
    int                      target;
569
 
 
570
 
    if (texture->target () == GL_TEXTURE_2D)
571
 
        target = COMP_FETCH_TARGET_2D;
572
 
    else
573
 
        target = COMP_FETCH_TARGET_RECT;
574
 
 
575
 
    foreach (BlurFunction &bf, srcBlurFunctions)
576
 
        if (bf.param == param && bf.target == target)
577
 
            return bf.id;
578
 
 
579
 
    if (data.status ())
580
 
    {
581
 
        static const char *temp[] = { "offset0", "offset1", "sum" };
582
 
        int         i;
583
 
        
584
 
        for (i = 0; i < sizeof (temp) / sizeof (temp[0]); i++)
585
 
            data.addTempHeaderOp (temp[i]);
586
 
 
587
 
        data.addDataOp (
588
 
            "MUL offset0, program.env[%d].xyzw, { 1.0, 1.0, 0.0, 0.0 };"
589
 
            "MUL offset1, program.env[%d].zwww, { 1.0, 1.0, 0.0, 0.0 };",
590
 
            param, param);
591
 
 
592
 
 
593
 
        switch (opt[BLUR_OPTION_FILTER].value ().i ()) {
594
 
            case BLUR_FILTER_4X_BILINEAR:
595
 
            default:
596
 
                data.addFetchOp ("output", "offset0", target);
597
 
                data.addDataOp ("MUL sum, output, 0.25;");
598
 
                data.addFetchOp ("output", "-offset0", target);
599
 
                data.addDataOp ("MAD sum, output, 0.25, sum;");
600
 
                data.addFetchOp ("output", "offset1", target);
601
 
                data.addDataOp ("MAD sum, output, 0.25, sum;");
602
 
                data.addFetchOp ("output", "-offset1", target);
603
 
                data.addDataOp ("MAD output, output, 0.25, sum;");
604
 
                break;
605
 
        }
606
 
 
607
 
        if (!data.status ())
608
 
            return 0;
609
 
 
610
 
        function.id     = data.createFragmentFunction ("blur");
611
 
        function.target = target;
612
 
        function.param  = param;
613
 
        function.unit   = 0;
614
 
 
615
 
        srcBlurFunctions.push_back (function);
616
 
 
617
 
        return function.id;
618
 
    }
619
 
 
620
 
    return 0;
621
 
}
622
 
 
623
 
GLFragment::FunctionId
624
 
BlurScreen::getDstBlurFragmentFunction (GLTexture *texture,
625
 
                                        int       param,
626
 
                                        int       unit,
627
 
                                        int       numITC,
628
 
                                        int       startTC)
629
 
{
630
 
    BlurFunction             function;
631
 
    GLFragment::FunctionData data;
632
 
    int                      target;
633
 
    char                     *targetString;
634
 
 
635
 
    if (texture->target () == GL_TEXTURE_2D)
636
 
    {
637
 
        target       = COMP_FETCH_TARGET_2D;
638
 
        targetString = (char *) "2D";
639
 
    }
640
 
    else
641
 
    {
642
 
        target       = COMP_FETCH_TARGET_RECT;
643
 
        targetString = (char *) "RECT";
644
 
    }
645
 
 
646
 
    foreach (BlurFunction &function, dstBlurFunctions)
647
 
        if (function.param   == param  &&
648
 
            function.target  == target &&
649
 
            function.unit    == unit   &&
650
 
            function.numITC  == numITC &&
651
 
            function.startTC == startTC)
652
 
            return function.id;
653
 
 
654
 
    if (data.status ())
655
 
    {
656
 
        static const char *temp[] = { "fCoord", "mask", "sum", "dst" };
657
 
        int               i, j;
658
 
        char              str[1024];
659
 
        int               saturation = opt[BLUR_OPTION_SATURATION].value ().i ();
660
 
        int               numIndirect;
661
 
        int               numIndirectOp;
662
 
        int               base, end, ITCbase;
663
 
 
664
 
        for (i = 0; i < sizeof (temp) / sizeof (temp[0]); i++)
665
 
            data.addTempHeaderOp (temp[i]);
666
 
 
667
 
        if (saturation < 100)
668
 
            data.addTempHeaderOp ("sat");
669
 
 
670
 
        switch (opt[BLUR_OPTION_FILTER].value ().i ()) {
671
 
            case BLUR_FILTER_4X_BILINEAR: {
672
 
                static const char *filterTemp[] = {
673
 
                    "t0", "t1", "t2", "t3",
674
 
                    "s0", "s1", "s2", "s3"
675
 
                };
676
 
 
677
 
                for (i = 0; i < sizeof (filterTemp) / sizeof (filterTemp[0]); i++)
678
 
                    data.addTempHeaderOp (filterTemp[i]);
679
 
 
680
 
                data.addFetchOp ("output", NULL, target);
681
 
                data.addColorOp ("output", "output");
682
 
 
683
 
                data.addDataOp (
684
 
                    "MUL fCoord, fragment.position, program.env[%d];",
685
 
                    param);
686
 
 
687
 
 
688
 
                data.addDataOp (
689
 
                    "ADD t0, fCoord, program.env[%d];"
690
 
                    "TEX s0, t0, texture[%d], %s;"
691
 
 
692
 
                    "SUB t1, fCoord, program.env[%d];"
693
 
                    "TEX s1, t1, texture[%d], %s;"
694
 
 
695
 
                    "MAD t2, program.env[%d], { -1.0, 1.0, 0.0, 0.0 }, fCoord;"
696
 
                    "TEX s2, t2, texture[%d], %s;"
697
 
 
698
 
                    "MAD t3, program.env[%d], { 1.0, -1.0, 0.0, 0.0 }, fCoord;"
699
 
                    "TEX s3, t3, texture[%d], %s;"
700
 
 
701
 
                    "MUL_SAT mask, output.a, program.env[%d];"
702
 
 
703
 
                    "MUL sum, s0, 0.25;"
704
 
                    "MAD sum, s1, 0.25, sum;"
705
 
                    "MAD sum, s2, 0.25, sum;"
706
 
                    "MAD sum, s3, 0.25, sum;",
707
 
 
708
 
                    param + 2, unit, targetString,
709
 
                    param + 2, unit, targetString,
710
 
                    param + 2, unit, targetString,
711
 
                    param + 2, unit, targetString,
712
 
                    param + 1);
713
 
 
714
 
            } break;
715
 
            case BLUR_FILTER_GAUSSIAN: {
716
 
 
717
 
                /* try to use only half of the available temporaries to keep
718
 
                   other plugins working */
719
 
                if ((maxTemp / 2) - 4 >
720
 
                     (numTexop + (numTexop - numITC)) * 2)
721
 
                {
722
 
                    numIndirect   = 1;
723
 
                    numIndirectOp = numTexop;
724
 
                }
725
 
                else
726
 
                {
727
 
                    i = MAX(((maxTemp / 2) - 4) / 4, 1);
728
 
                    numIndirect = ceil ((float)numTexop / (float)i);
729
 
                    numIndirectOp = ceil ((float)numTexop / (float)numIndirect);
730
 
                }
731
 
 
732
 
                /* we need to define all coordinate temporaries if we have
733
 
                   multiple indirection steps */
734
 
                j = (numIndirect > 1) ? 0 : numITC;
735
 
 
736
 
                for (i = 0; i < numIndirectOp * 2; i++)
737
 
                {
738
 
                    snprintf (str, 1024, "pix_%d", i);
739
 
                    data.addTempHeaderOp (str);
740
 
                }
741
 
 
742
 
                for (i = j * 2; i < numIndirectOp * 2; i++)
743
 
                {
744
 
                    snprintf (str, 1024, "coord_%d", i);
745
 
                    data.addTempHeaderOp (str);
746
 
                }
747
 
 
748
 
        
749
 
                data.addFetchOp ("output", NULL, target);
750
 
                data.addColorOp ("output", "output");
751
 
 
752
 
                data.addDataOp (
753
 
                    "MUL fCoord, fragment.position, program.env[%d];",
754
 
                    param);
755
 
 
756
 
 
757
 
                data.addDataOp ("TEX sum, fCoord, texture[%d], %s;",
758
 
                                unit + 1, targetString);
759
 
 
760
 
 
761
 
                data.addDataOp ("MUL_SAT mask, output.a, program.env[%d];"
762
 
                                "MUL sum, sum, %f;",
763
 
                                param + 1, amp[numTexop]);
764
 
 
765
 
                for (j = 0; j < numIndirect; j++)
766
 
                {
767
 
                    base = j * numIndirectOp;
768
 
                    end  = MIN ((j + 1) * numIndirectOp, numTexop) - base;
769
 
                    
770
 
                    ITCbase = MAX (numITC - base, 0);
771
 
 
772
 
                    for (i = ITCbase; i < end; i++)
773
 
                    {
774
 
                        data.addDataOp (
775
 
                            "ADD coord_%d, fCoord, {0.0, %g, 0.0, 0.0};"
776
 
                            "SUB coord_%d, fCoord, {0.0, %g, 0.0, 0.0};",
777
 
                            i * 2, pos[base + i] * ty,
778
 
                            (i * 2) + 1, pos[base + i] * ty);
779
 
                    }
780
 
 
781
 
                    for (i = 0; i < ITCbase; i++)
782
 
                    {
783
 
                        data.addDataOp (
784
 
                            "TXP pix_%d, fragment.texcoord[%d], texture[%d], %s;"
785
 
                            "TXP pix_%d, fragment.texcoord[%d], texture[%d], %s;",
786
 
                            i * 2, startTC + ((i + base) * 2),
787
 
                            unit + 1, targetString,
788
 
                            (i * 2) + 1, startTC + 1 + ((i + base) * 2),
789
 
                            unit + 1, targetString);
790
 
                    }
791
 
 
792
 
                    for (i = ITCbase; i < end; i++)
793
 
                    {
794
 
                        data.addDataOp (
795
 
                            "TEX pix_%d, coord_%d, texture[%d], %s;"
796
 
                            "TEX pix_%d, coord_%d, texture[%d], %s;",
797
 
                            i * 2, i * 2,
798
 
                            unit + 1, targetString,
799
 
                            (i * 2) + 1, (i * 2) + 1,
800
 
                            unit + 1, targetString);
801
 
                    }
802
 
 
803
 
                    for (i = 0; i < end * 2; i++)
804
 
                    {
805
 
                        data.addDataOp (
806
 
                            "MAD sum, pix_%d, %f, sum;",
807
 
                            i, amp[base + (i / 2)]);
808
 
                    }
809
 
                }
810
 
 
811
 
            } break;
812
 
            case BLUR_FILTER_MIPMAP:
813
 
                data.addFetchOp ("output", NULL, target);
814
 
                data.addColorOp ("output", "output");
815
 
 
816
 
                data.addDataOp (
817
 
                    "MUL fCoord, fragment.position, program.env[%d].xyzz;"
818
 
                    "MOV fCoord.w, program.env[%d].w;"
819
 
                    "TXB sum, fCoord, texture[%d], %s;"
820
 
                    "MUL_SAT mask, output.a, program.env[%d];",
821
 
                    param, param, unit, targetString,
822
 
                    param + 1);
823
 
 
824
 
                break;
825
 
        }
826
 
 
827
 
        if (saturation < 100)
828
 
        {
829
 
            data.addDataOp (
830
 
                "MUL sat, sum, { 1.0, 1.0, 1.0, 0.0 };"
831
 
                "DP3 sat, sat, { %f, %f, %f, %f };"
832
 
                "LRP sum.xyz, %f, sum, sat;",
833
 
                RED_SATURATION_WEIGHT, GREEN_SATURATION_WEIGHT,
834
 
                BLUE_SATURATION_WEIGHT, 0.0f, saturation / 100.0f);
835
 
        }
836
 
 
837
 
        data.addDataOp (
838
 
            "MAD dst, mask, -output.a, mask;"
839
 
            "MAD output.rgb, sum, dst.a, output;"
840
 
            "ADD output.a, output.a, dst.a;");
841
 
 
842
 
        if (!data.status ())
843
 
        {
844
 
            return 0;
845
 
        }
846
 
 
847
 
 
848
 
 
849
 
        function.id      = data.createFragmentFunction ("blur");
850
 
        function.target  = target;
851
 
        function.param   = param;
852
 
        function.unit    = unit;
853
 
        function.numITC  = numITC;
854
 
        function.startTC = startTC;
855
 
 
856
 
        dstBlurFunctions.push_back (function);
857
 
 
858
 
        return function.id;
859
 
    }
860
 
 
861
 
    return 0;
862
 
}
863
 
 
864
 
bool
865
 
BlurScreen::projectVertices (CompOutput     *output,
866
 
                             const GLMatrix &transform,
867
 
                             const float    *object,
868
 
                             float          *scr,
869
 
                             int            n)
870
 
{
871
 
    GLdouble dProjection[16];
872
 
    GLdouble dModel[16];
873
 
    GLint    viewport[4];
874
 
    double   x, y, z;
875
 
    int      i;
876
 
 
877
 
    viewport[0] = output->x1 ();
878
 
    viewport[1] = screen->height () - output->y2 ();
879
 
    viewport[2] = output->width ();
880
 
    viewport[3] = output->height ();
881
 
 
882
 
    for (i = 0; i < 16; i++)
883
 
    {
884
 
        dModel[i]      = transform.getMatrix ()[i];
885
 
        dProjection[i] = gScreen->projectionMatrix ()[i];
886
 
    }
887
 
 
888
 
    while (n--)
889
 
    {
890
 
        if (!gluProject (object[0], object[1], object[2],
891
 
                         dModel, dProjection, viewport,
892
 
                         &x, &y, &z))
893
 
            return false;
894
 
 
895
 
        scr[0] = x;
896
 
        scr[1] = y;
897
 
 
898
 
        object += 3;
899
 
        scr += 2;
900
 
    }
901
 
 
902
 
    return true;
903
 
}
904
 
 
905
 
bool
906
 
BlurScreen::loadFragmentProgram (GLuint *program,
907
 
                                 const char *string)
908
 
{
909
 
    GLint errorPos;
910
 
 
911
 
    /* clear errors */
912
 
    glGetError ();
913
 
 
914
 
    if (!*program)
915
 
        (*GL::genPrograms) (1, program);
916
 
 
917
 
    (*GL::bindProgram) (GL_FRAGMENT_PROGRAM_ARB, *program);
918
 
    (*GL::programString) (GL_FRAGMENT_PROGRAM_ARB,
919
 
                          GL_PROGRAM_FORMAT_ASCII_ARB,
920
 
                          strlen (string), string);
921
 
 
922
 
    glGetIntegerv (GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
923
 
    if (glGetError () != GL_NO_ERROR || errorPos != -1)
924
 
    {
925
 
        compLogMessage ("blur", CompLogLevelError,
926
 
                        "Failed to load blur program %s", string);
927
 
 
928
 
        (*GL::deletePrograms) (1, program);
929
 
        *program = 0;
930
 
 
931
 
        return false;
932
 
    }
933
 
 
934
 
    return true;
935
 
}
936
 
 
937
 
bool
938
 
BlurScreen::loadFilterProgram (int numITC)
939
 
{
940
 
    char  buffer[4096];
941
 
    char  *targetString;
942
 
    char  *str = buffer;
943
 
    int   i, j;
944
 
    int   numIndirect;
945
 
    int   numIndirectOp;
946
 
    int   base, end, ITCbase;
947
 
 
948
 
    if (target == GL_TEXTURE_2D)
949
 
        targetString = (char *) "2D";
950
 
    else
951
 
        targetString = (char *) "RECT";
952
 
 
953
 
    str += sprintf (str,
954
 
                    "!!ARBfp1.0"
955
 
                    "ATTRIB texcoord = fragment.texcoord[0];"
956
 
                    "TEMP sum;");
957
 
 
958
 
    if (maxTemp - 1 > (numTexop + (numTexop - numITC)) * 2)
959
 
    {
960
 
        numIndirect   = 1;
961
 
        numIndirectOp = numTexop;
962
 
    }
963
 
    else
964
 
    {
965
 
        i = (maxTemp - 1) / 4;
966
 
        numIndirect = ceil ((float)numTexop / (float)i);
967
 
        numIndirectOp = ceil ((float)numTexop / (float)numIndirect);
968
 
    }
969
 
 
970
 
    /* we need to define all coordinate temporaries if we have
971
 
       multiple indirection steps */
972
 
    j = (numIndirect > 1) ? 0 : numITC;
973
 
 
974
 
    for (i = 0; i < numIndirectOp; i++)
975
 
        str += sprintf (str,"TEMP pix_%d, pix_%d;", i * 2, (i * 2) + 1);
976
 
 
977
 
    for (i = j; i < numIndirectOp; i++)
978
 
        str += sprintf (str,"TEMP coord_%d, coord_%d;", i * 2, (i * 2) + 1);
979
 
 
980
 
    str += sprintf (str,
981
 
                    "TEX sum, texcoord, texture[0], %s;",
982
 
                    targetString);
983
 
 
984
 
    str += sprintf (str,
985
 
                    "MUL sum, sum, %f;",
986
 
                    amp[numTexop]);
987
 
 
988
 
    for (j = 0; j < numIndirect; j++)
989
 
    {
990
 
        base = j * numIndirectOp;
991
 
        end  = MIN ((j + 1) * numIndirectOp, numTexop) - base;
992
 
        
993
 
        ITCbase = MAX (numITC - base, 0);
994
 
 
995
 
        for (i = ITCbase; i < end; i++)
996
 
            str += sprintf (str,
997
 
                            "ADD coord_%d, texcoord, {%g, 0.0, 0.0, 0.0};"
998
 
                            "SUB coord_%d, texcoord, {%g, 0.0, 0.0, 0.0};",
999
 
                            i * 2, pos[base + i] * tx,
1000
 
                            (i * 2) + 1, pos[base + i] * tx);
1001
 
 
1002
 
        for (i = 0; i < ITCbase; i++)
1003
 
            str += sprintf (str,
1004
 
                "TEX pix_%d, fragment.texcoord[%d], texture[0], %s;"
1005
 
                "TEX pix_%d, fragment.texcoord[%d], texture[0], %s;",
1006
 
                i * 2, ((i + base) * 2) + 1, targetString,
1007
 
                (i * 2) + 1, ((i + base) * 2) + 2, targetString);
1008
 
 
1009
 
        for (i = ITCbase; i < end; i++)
1010
 
            str += sprintf (str,
1011
 
                            "TEX pix_%d, coord_%d, texture[0], %s;"
1012
 
                            "TEX pix_%d, coord_%d, texture[0], %s;",
1013
 
                            i * 2, i * 2, targetString,
1014
 
                            (i * 2) + 1, (i * 2) + 1, targetString);
1015
 
 
1016
 
        for (i = 0; i < end * 2; i++)
1017
 
            str += sprintf (str,
1018
 
                            "MAD sum, pix_%d, %f, sum;",
1019
 
                            i, amp[base + (i / 2)]);
1020
 
    }
1021
 
 
1022
 
    str += sprintf (str,
1023
 
                    "MOV result.color, sum;"
1024
 
                    "END");
1025
 
 
1026
 
    return loadFragmentProgram (&program, buffer);
1027
 
}
1028
 
 
1029
 
bool
1030
 
BlurScreen::fboPrologue ()
1031
 
{
1032
 
    if (!fbo)
1033
 
        return false;
1034
 
 
1035
 
    (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, fbo);
1036
 
 
1037
 
    /* bind texture and check status the first time */
1038
 
    if (!fboStatus)
1039
 
    {
1040
 
        (*GL::framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
1041
 
                                     GL_COLOR_ATTACHMENT0_EXT,
1042
 
                                     target, texture[1],
1043
 
                                     0);
1044
 
 
1045
 
        fboStatus = (*GL::checkFramebufferStatus) (GL_FRAMEBUFFER_EXT);
1046
 
        if (fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
1047
 
        {
1048
 
            compLogMessage ("blur", CompLogLevelError,
1049
 
                            "Framebuffer incomplete");
1050
 
 
1051
 
            (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
1052
 
            (*GL::deleteFramebuffers) (1, &fbo);
1053
 
 
1054
 
            fbo = 0;
1055
 
 
1056
 
            return false;
1057
 
        }
1058
 
    }
1059
 
 
1060
 
    glPushAttrib (GL_VIEWPORT_BIT | GL_ENABLE_BIT);
1061
 
 
1062
 
    glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
1063
 
    glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
1064
 
 
1065
 
    glDisable (GL_CLIP_PLANE0);
1066
 
    glDisable (GL_CLIP_PLANE1);
1067
 
    glDisable (GL_CLIP_PLANE2);
1068
 
    glDisable (GL_CLIP_PLANE3);
1069
 
 
1070
 
    glViewport (0, 0, width, height);
1071
 
    glMatrixMode (GL_PROJECTION);
1072
 
    glPushMatrix ();
1073
 
    glLoadIdentity ();
1074
 
    glOrtho (0.0, width, 0.0, height, -1.0, 1.0);
1075
 
    glMatrixMode (GL_MODELVIEW);
1076
 
    glPushMatrix ();
1077
 
    glLoadIdentity ();
1078
 
 
1079
 
    return true;
1080
 
}
1081
 
 
1082
 
void
1083
 
BlurScreen::fboEpilogue ()
1084
 
{
1085
 
    (*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
1086
 
 
1087
 
    glMatrixMode (GL_PROJECTION);
1088
 
    glLoadIdentity ();
1089
 
    glMatrixMode (GL_MODELVIEW);
1090
 
    glLoadIdentity ();
1091
 
    glDepthRange (0, 1);
1092
 
    glViewport (-1, -1, 2, 2);
1093
 
    glRasterPos2f (0, 0);
1094
 
 
1095
 
    gScreen->resetRasterPos ();
1096
 
 
1097
 
    glMatrixMode (GL_PROJECTION);
1098
 
    glPopMatrix ();
1099
 
    glMatrixMode (GL_MODELVIEW);
1100
 
    glPopMatrix ();
1101
 
 
1102
 
    glDrawBuffer (GL_BACK);
1103
 
    glReadBuffer (GL_BACK);
1104
 
 
1105
 
    glPopAttrib ();
1106
 
}
1107
 
 
1108
 
bool
1109
 
BlurScreen::fboUpdate (BoxPtr pBox,
1110
 
                       int    nBox)
1111
 
{
1112
 
    int  i, y, iTC = 0;
1113
 
    Bool wasCulled = glIsEnabled (GL_CULL_FACE);
1114
 
 
1115
 
    if (GL::maxTextureUnits &&
1116
 
        opt[BLUR_OPTION_INDEPENDENT_TEX].value ().b ())
1117
 
        iTC = MIN ((GL::maxTextureUnits - 1) / 2, numTexop);
1118
 
 
1119
 
    if (!program)
1120
 
        if (!loadFilterProgram (iTC))
1121
 
            return false;
1122
 
 
1123
 
    if (!fboPrologue ())
1124
 
        return false;
1125
 
 
1126
 
    glDisable (GL_CULL_FACE);
1127
 
 
1128
 
    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1129
 
 
1130
 
    glBindTexture (target, texture[0]);
1131
 
 
1132
 
    glEnable (GL_FRAGMENT_PROGRAM_ARB);
1133
 
    (*GL::bindProgram) (GL_FRAGMENT_PROGRAM_ARB, program);
1134
 
 
1135
 
    glBegin (GL_QUADS);
1136
 
 
1137
 
    while (nBox--)
1138
 
    {
1139
 
        y = screen->height () - pBox->y2;
1140
 
 
1141
 
        for (i = 0; i < iTC; i++)
1142
 
        {
1143
 
            (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1144
 
                                    tx * (pBox->x1 + pos[i]),
1145
 
                                    ty * y);
1146
 
            (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1147
 
                                    tx * (pBox->x1 - pos[i]),
1148
 
                                    ty * y);
1149
 
        }
1150
 
 
1151
 
        glTexCoord2f (tx * pBox->x1, ty * y);
1152
 
        glVertex2i   (pBox->x1, y);
1153
 
 
1154
 
        for (i = 0; i < iTC; i++)
1155
 
        {
1156
 
            (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1157
 
                                    tx * (pBox->x2 + pos[i]),
1158
 
                                    ty * y);
1159
 
            (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1160
 
                                    tx * (pBox->x2 - pos[i]),
1161
 
                                    ty * y);
1162
 
        }
1163
 
 
1164
 
        glTexCoord2f (tx * pBox->x2, ty * y);
1165
 
        glVertex2i   (pBox->x2, y);
1166
 
 
1167
 
        y = screen->height () - pBox->y1;
1168
 
 
1169
 
        for (i = 0; i < iTC; i++)
1170
 
        {
1171
 
            (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1172
 
                                    tx * (pBox->x2 + pos[i]),
1173
 
                                    ty * y);
1174
 
            (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1175
 
                                    tx * (pBox->x2 - pos[i]),
1176
 
                                    ty * y);
1177
 
        }
1178
 
 
1179
 
        glTexCoord2f (tx * pBox->x2, ty * y);
1180
 
        glVertex2i   (pBox->x2, y);
1181
 
 
1182
 
        for (i = 0; i < iTC; i++)
1183
 
        {
1184
 
            (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1185
 
                                    tx * (pBox->x1 + pos[i]),
1186
 
                                    ty * y);
1187
 
            (*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1188
 
                                    tx * (pBox->x1 - pos[i]),
1189
 
                                    ty * y);
1190
 
        }
1191
 
 
1192
 
        glTexCoord2f (tx * pBox->x1, ty * y);
1193
 
        glVertex2i   (pBox->x1, y);
1194
 
 
1195
 
        pBox++;
1196
 
    }
1197
 
 
1198
 
    glEnd ();
1199
 
 
1200
 
    glDisable (GL_FRAGMENT_PROGRAM_ARB);
1201
 
 
1202
 
    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1203
 
 
1204
 
    if (wasCulled)
1205
 
        glEnable (GL_CULL_FACE);
1206
 
 
1207
 
    fboEpilogue ();
1208
 
 
1209
 
    return true;
1210
 
}
1211
 
 
1212
 
#define MAX_VERTEX_PROJECT_COUNT 20
1213
 
 
1214
 
void
1215
 
BlurWindow::projectRegion (CompOutput     *output,
1216
 
                           const GLMatrix &transform)
1217
 
{
1218
 
    float      scrv[MAX_VERTEX_PROJECT_COUNT * 2];
1219
 
    float      vertices[MAX_VERTEX_PROJECT_COUNT * 3];
1220
 
    int        nVertices, nQuadCombine;
1221
 
    int        i, j, stride;
1222
 
    float      *v, *vert;
1223
 
    float      minX, maxX, minY, maxY, minZ, maxZ;
1224
 
    float      *scr;
1225
 
 
1226
 
    GLTexture::MatrixList ml;
1227
 
    GLWindow::Geometry    *gm;
1228
 
 
1229
 
    gWindow->geometry ().reset ();
1230
 
    gWindow->glAddGeometry (ml, bScreen->tmpRegion2, infiniteRegion);
1231
 
 
1232
 
    if (!gWindow->geometry ().vCount)
1233
 
        return;
1234
 
 
1235
 
    gm = &gWindow->geometry ();
1236
 
 
1237
 
    nVertices    = (gm->indexCount) ? gm->indexCount: gm->vCount;
1238
 
    nQuadCombine = 1;
1239
 
 
1240
 
    stride = gm->vertexStride;
1241
 
    vert = gm->vertices + (stride - 3);
1242
 
 
1243
 
    /* we need to find the best value here */
1244
 
    if (nVertices <= MAX_VERTEX_PROJECT_COUNT)
1245
 
    {
1246
 
        for (i = 0; i < nVertices; i++)
1247
 
        {
1248
 
            if (gm->indexCount)
1249
 
            {
1250
 
                v = vert + (stride * gm->indices[i]);
1251
 
            }
1252
 
            else
1253
 
            {
1254
 
                v = vert + (stride * i);
1255
 
            }
1256
 
 
1257
 
            vertices[i * 3] = v[0];
1258
 
            vertices[(i * 3) + 1] = v[1];
1259
 
            vertices[(i * 3) + 2] = v[2];
1260
 
        }
1261
 
    }
1262
 
    else
1263
 
    {
1264
 
        minX = screen->width ();
1265
 
        maxX = 0;
1266
 
        minY = screen->height ();
1267
 
        maxY = 0;
1268
 
        minZ = 1000000;
1269
 
        maxZ = -1000000;
1270
 
 
1271
 
        for (i = 0; i < gm->vCount; i++)
1272
 
        {
1273
 
            v = vert + (stride * i);
1274
 
 
1275
 
            if (v[0] < minX)
1276
 
                minX = v[0];
1277
 
 
1278
 
            if (v[0] > maxX)
1279
 
                maxX = v[0];
1280
 
 
1281
 
            if (v[1] < minY)
1282
 
                minY = v[1];
1283
 
 
1284
 
            if (v[1] > maxY)
1285
 
                maxY = v[1];
1286
 
 
1287
 
            if (v[2] < minZ)
1288
 
                minZ = v[2];
1289
 
 
1290
 
            if (v[2] > maxZ)
1291
 
                maxZ = v[2];
1292
 
        }
1293
 
 
1294
 
        vertices[0] = vertices[9]  = minX;
1295
 
        vertices[1] = vertices[4]  = minY;
1296
 
        vertices[3] = vertices[6]  = maxX;
1297
 
        vertices[7] = vertices[10] = maxY;
1298
 
        vertices[2] = vertices[5]  = maxZ;
1299
 
        vertices[8] = vertices[11] = maxZ;
1300
 
 
1301
 
        nVertices = 4;
1302
 
 
1303
 
        if (maxZ != minZ)
1304
 
        {
1305
 
            vertices[12] = vertices[21] = minX;
1306
 
            vertices[13] = vertices[16] = minY;
1307
 
            vertices[15] = vertices[18] = maxX;
1308
 
            vertices[19] = vertices[22] = maxY;
1309
 
            vertices[14] = vertices[17] = minZ;
1310
 
            vertices[20] = vertices[23] = minZ;
1311
 
            nQuadCombine = 2;
1312
 
        }
1313
 
    }
1314
 
 
1315
 
    if (!bScreen->projectVertices (output, transform, vertices, scrv,
1316
 
                                   nVertices * nQuadCombine))
1317
 
        return;
1318
 
 
1319
 
    for (i = 0; i < nVertices / 4; i++)
1320
 
    {
1321
 
        scr = scrv + (i * 4 * 2);
1322
 
 
1323
 
        minX = screen->width ();
1324
 
        maxX = 0;
1325
 
        minY = screen->height ();
1326
 
        maxY = 0;
1327
 
 
1328
 
        for (j = 0; j < 8 * nQuadCombine; j += 2)
1329
 
        {
1330
 
            if (scr[j] < minX)
1331
 
                minX = scr[j];
1332
 
 
1333
 
            if (scr[j] > maxX)
1334
 
                maxX = scr[j];
1335
 
 
1336
 
            if (scr[j + 1] < minY)
1337
 
                minY = scr[j + 1];
1338
 
 
1339
 
            if (scr[j + 1] > maxY)
1340
 
                maxY = scr[j + 1];
1341
 
        }
1342
 
 
1343
 
        int x1, y1, x2, y2;
1344
 
 
1345
 
        x1 = minX - bScreen->filterRadius;
1346
 
        y1 = screen->height () - maxY - bScreen->filterRadius;
1347
 
        x2 = maxX + bScreen->filterRadius + 0.5f;
1348
 
        y2 = screen->height () - minY + bScreen->filterRadius + 0.5f;
1349
 
 
1350
 
 
1351
 
        bScreen->tmpRegion3 += CompRect (x1, y1, x2 - x1, y2 - y1);
1352
 
 
1353
 
    }
1354
 
}
1355
 
 
1356
 
bool
1357
 
BlurWindow::updateDstTexture (const GLMatrix &transform,
1358
 
                              CompRect       *pExtents,
1359
 
                              int            clientThreshold)
1360
 
{
1361
 
    int        y;
1362
 
    int        filter;
1363
 
 
1364
 
    filter = bScreen->opt[BLUR_OPTION_FILTER].value ().i ();
1365
 
 
1366
 
    bScreen->tmpRegion3 = CompRegion ();
1367
 
 
1368
 
    if (filter == BLUR_FILTER_GAUSSIAN)
1369
 
    {
1370
 
 
1371
 
        if (state[BLUR_STATE_DECOR].threshold)
1372
 
        {
1373
 
            int  xx, yy, ww, hh;
1374
 
            // top
1375
 
            xx = window->x () - window->output ().left;
1376
 
            yy = window->y () - window->output ().top;
1377
 
            ww = window->width () + window->output ().left + window->output ().right;
1378
 
            hh = window->output ().top;
1379
 
 
1380
 
            bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1381
 
                CompRect (xx, yy, ww, hh));
1382
 
 
1383
 
            if (!bScreen->tmpRegion2.isEmpty ())
1384
 
                projectRegion (bScreen->output, transform);
1385
 
 
1386
 
            // bottom
1387
 
            xx = window->x () - window->output ().left;
1388
 
            yy = window->y () + window->height ();
1389
 
            ww = window->width () + window->output ().left + window->output ().right;
1390
 
            hh = window->output ().bottom;
1391
 
 
1392
 
            bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1393
 
                CompRect (xx, yy, ww, hh));
1394
 
 
1395
 
            if (!bScreen->tmpRegion2.isEmpty ())
1396
 
                projectRegion (bScreen->output, transform);
1397
 
 
1398
 
            // left
1399
 
            xx = window->x () - window->output ().left;
1400
 
            yy = window->y ();
1401
 
            ww = window->output ().left;
1402
 
            hh = window->height ();
1403
 
 
1404
 
            bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1405
 
                CompRect (xx, yy, ww, hh));
1406
 
 
1407
 
            if (!bScreen->tmpRegion2.isEmpty ())
1408
 
                projectRegion (bScreen->output, transform);
1409
 
 
1410
 
            // right
1411
 
            xx = window->x () + window->width ();
1412
 
            yy = window->y ();
1413
 
            ww = window->output ().right;
1414
 
            hh = window->height ();
1415
 
 
1416
 
            bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1417
 
                CompRect (xx, yy, ww, hh));
1418
 
 
1419
 
            if (!bScreen->tmpRegion2.isEmpty ())
1420
 
                projectRegion (bScreen->output, transform);
1421
 
        }
1422
 
 
1423
 
        if (clientThreshold)
1424
 
        {
1425
 
            // center
1426
 
            bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1427
 
                CompRect (window->x (),
1428
 
                          window->y (),
1429
 
                          window->width (),
1430
 
                          window->height ()));
1431
 
 
1432
 
            if (!bScreen->tmpRegion2.isEmpty ())
1433
 
                projectRegion (bScreen->output, transform);
1434
 
        }
1435
 
    }
1436
 
    else
1437
 
    {
1438
 
        // center
1439
 
        bScreen->tmpRegion2 = bScreen->tmpRegion;
1440
 
 
1441
 
        if (!bScreen->tmpRegion2.isEmpty ())
1442
 
            projectRegion (bScreen->output, transform);
1443
 
    }
1444
 
 
1445
 
    bScreen->tmpRegion = bScreen->region.intersected (bScreen->tmpRegion3);
1446
 
 
1447
 
    if (bScreen->tmpRegion.isEmpty ())
1448
 
        return false;
1449
 
 
1450
 
    *pExtents = bScreen->tmpRegion.boundingRect ();
1451
 
 
1452
 
    if (!bScreen->texture[0] || bScreen->width != screen->width () ||
1453
 
        bScreen->height != screen->height ())
1454
 
    {
1455
 
        int i, textures = 1;
1456
 
 
1457
 
        bScreen->width  = screen->width ();
1458
 
        bScreen->height = screen->height ();
1459
 
 
1460
 
        if (GL::textureNonPowerOfTwo ||
1461
 
            (POWER_OF_TWO (bScreen->width) && POWER_OF_TWO (bScreen->height)))
1462
 
        {
1463
 
            bScreen->target = GL_TEXTURE_2D;
1464
 
            bScreen->tx = 1.0f / bScreen->width;
1465
 
            bScreen->ty = 1.0f / bScreen->height;
1466
 
        }
1467
 
        else
1468
 
        {
1469
 
            bScreen->target = GL_TEXTURE_RECTANGLE_NV;
1470
 
            bScreen->tx = 1;
1471
 
            bScreen->ty = 1;
1472
 
        }
1473
 
 
1474
 
        if (filter == BLUR_FILTER_GAUSSIAN)
1475
 
        {
1476
 
            if (GL::fbo && !bScreen->fbo)
1477
 
                (*GL::genFramebuffers) (1, &bScreen->fbo);
1478
 
 
1479
 
            if (!bScreen->fbo)
1480
 
                compLogMessage ("blur", CompLogLevelError,
1481
 
                                "Failed to create framebuffer object");
1482
 
 
1483
 
            textures = 2;
1484
 
        }
1485
 
 
1486
 
        bScreen->fboStatus = FALSE;
1487
 
 
1488
 
        for (i = 0; i < textures; i++)
1489
 
        {
1490
 
            if (!bScreen->texture[i])
1491
 
                glGenTextures (1, &bScreen->texture[i]);
1492
 
 
1493
 
            glBindTexture (bScreen->target, bScreen->texture[i]);
1494
 
 
1495
 
            glTexImage2D (bScreen->target, 0, GL_RGB,
1496
 
                          bScreen->width,
1497
 
                          bScreen->height,
1498
 
                          0, GL_BGRA,
1499
 
 
1500
 
#if IMAGE_BYTE_ORDER == MSBFirst
1501
 
                          GL_UNSIGNED_INT_8_8_8_8_REV,
1502
 
#else
1503
 
                          GL_UNSIGNED_BYTE,
1504
 
#endif
1505
 
 
1506
 
                          NULL);
1507
 
 
1508
 
            glTexParameteri (bScreen->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1509
 
            glTexParameteri (bScreen->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1510
 
 
1511
 
            if (filter == BLUR_FILTER_MIPMAP)
1512
 
            {
1513
 
                if (!GL::fbo)
1514
 
                {
1515
 
                    compLogMessage ("blur", CompLogLevelWarn,
1516
 
                             "GL_EXT_framebuffer_object extension "
1517
 
                             "is required for mipmap filter");
1518
 
                }
1519
 
                else if (bScreen->target != GL_TEXTURE_2D)
1520
 
                {
1521
 
                    compLogMessage ("blur", CompLogLevelWarn,
1522
 
                             "GL_ARB_texture_non_power_of_two "
1523
 
                             "extension is required for mipmap filter");
1524
 
                }
1525
 
                else
1526
 
                {
1527
 
                    glTexParameteri (bScreen->target, GL_TEXTURE_MIN_FILTER,
1528
 
                                     GL_LINEAR_MIPMAP_LINEAR);
1529
 
                    glTexParameteri (bScreen->target, GL_TEXTURE_MAG_FILTER,
1530
 
                                     GL_LINEAR_MIPMAP_LINEAR);
1531
 
                }
1532
 
            }
1533
 
 
1534
 
            glTexParameteri (bScreen->target, GL_TEXTURE_WRAP_S,
1535
 
                             GL_CLAMP_TO_EDGE);
1536
 
            glTexParameteri (bScreen->target, GL_TEXTURE_WRAP_T,
1537
 
                             GL_CLAMP_TO_EDGE);
1538
 
 
1539
 
            glCopyTexSubImage2D (bScreen->target, 0, 0, 0, 0, 0,
1540
 
                                 bScreen->width, bScreen->height);
1541
 
        }
1542
 
    }
1543
 
    else
1544
 
    {
1545
 
        glBindTexture (bScreen->target, bScreen->texture[0]);
1546
 
 
1547
 
        CompRect br = bScreen->tmpRegion.boundingRect ();
1548
 
 
1549
 
        y = screen->height () - br.y2 ();
1550
 
 
1551
 
        glCopyTexSubImage2D (bScreen->target, 0,
1552
 
                             br.x1 (), y,
1553
 
                             br.x1 (), y,
1554
 
                             br.width (),
1555
 
                             br.height ());
1556
 
    }
1557
 
 
1558
 
    switch (filter) {
1559
 
        case BLUR_FILTER_GAUSSIAN:
1560
 
            return bScreen->fboUpdate (bScreen->tmpRegion.handle()->rects,
1561
 
                                       bScreen->tmpRegion.numRects ());
1562
 
        case BLUR_FILTER_MIPMAP:
1563
 
            (*GL::generateMipmap) (bScreen->target);
1564
 
            break;
1565
 
        case BLUR_FILTER_4X_BILINEAR:
1566
 
            break;
1567
 
    }
1568
 
 
1569
 
    glBindTexture (bScreen->target, 0);
1570
 
 
1571
 
    return true;
1572
 
}
1573
 
 
1574
 
bool
1575
 
BlurWindow::glDraw (const GLMatrix     &transform,
1576
 
                    GLFragment::Attrib &attrib,
1577
 
                    const CompRegion   &region,
1578
 
                    unsigned int       mask)
1579
 
{
1580
 
    bool       status;
1581
 
 
1582
 
    if (bScreen->alphaBlur && !region.isEmpty ())
1583
 
    {
1584
 
        int clientThreshold;
1585
 
 
1586
 
        /* only care about client window blurring when it's translucent */
1587
 
        if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
1588
 
            clientThreshold = state[BLUR_STATE_CLIENT].threshold;
1589
 
        else
1590
 
            clientThreshold = 0;
1591
 
 
1592
 
        if (state[BLUR_STATE_DECOR].threshold || clientThreshold)
1593
 
        {
1594
 
            bool       clipped = FALSE;
1595
 
            CompRect   box (0, 0, 0, 0);
1596
 
            CompRegion reg;
1597
 
            int        i;
1598
 
 
1599
 
            bScreen->mvp = GLMatrix (bScreen->gScreen->projectionMatrix ());
1600
 
            bScreen->mvp *= transform;
1601
 
 
1602
 
            if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
1603
 
                reg = infiniteRegion;
1604
 
            else
1605
 
                reg = region;
1606
 
 
1607
 
            bScreen->tmpRegion = this->region.intersected (reg);
1608
 
            if (!bScreen->blurOcclusion &&
1609
 
                !(mask & PAINT_WINDOW_TRANSFORMED_MASK))
1610
 
                bScreen->tmpRegion -= clip; 
1611
 
 
1612
 
            if (updateDstTexture (transform, &box, clientThreshold))
1613
 
            {
1614
 
                if (clientThreshold)
1615
 
                {
1616
 
                    if (state[BLUR_STATE_CLIENT].clipped)
1617
 
                    {
1618
 
                        if (bScreen->stencilBits)
1619
 
                        {
1620
 
                            state[BLUR_STATE_CLIENT].active = true;
1621
 
                            clipped = true;
1622
 
                        }
1623
 
                    }
1624
 
                    else
1625
 
                    {
1626
 
                        state[BLUR_STATE_CLIENT].active = true;
1627
 
                    }
1628
 
                }
1629
 
 
1630
 
                if (state[BLUR_STATE_DECOR].threshold)
1631
 
                {
1632
 
                    if (state[BLUR_STATE_DECOR].clipped)
1633
 
                    {
1634
 
                        if (bScreen->stencilBits)
1635
 
                        {
1636
 
                            state[BLUR_STATE_DECOR].active = true;
1637
 
                            clipped = true;
1638
 
                        }
1639
 
                    }
1640
 
                    else
1641
 
                    {
1642
 
                        state[BLUR_STATE_DECOR].active = true;
1643
 
                    }
1644
 
                }
1645
 
 
1646
 
                if (!bScreen->blurOcclusion && !clip.isEmpty ())
1647
 
                    clipped = true;
1648
 
            }
1649
 
 
1650
 
            if (!bScreen->blurOcclusion)
1651
 
                bScreen->tmpRegion = this->region - clip;
1652
 
            else
1653
 
                bScreen->tmpRegion = this->region;
1654
 
 
1655
 
            if (!clientThreshold)
1656
 
            {
1657
 
                bScreen->tmpRegion -= CompRect (window->x (),
1658
 
                                                window->x () + window->width (),
1659
 
                                                window->y (),
1660
 
                                                window->y () + window->height ());
1661
 
            }
1662
 
 
1663
 
            if (clipped)
1664
 
            {
1665
 
                GLTexture::MatrixList ml;
1666
 
 
1667
 
                gWindow->geometry ().reset ();
1668
 
                
1669
 
                gWindow->glAddGeometry (ml, bScreen->tmpRegion, reg);
1670
 
                if (gWindow->geometry ().vCount)
1671
 
                {
1672
 
                    CompRect clearBox = bScreen->stencilBox;
1673
 
 
1674
 
                    bScreen->stencilBox = box;
1675
 
 
1676
 
                    glEnable (GL_STENCIL_TEST);
1677
 
                    glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1678
 
 
1679
 
                    if (clearBox.x2 () > clearBox.x1 () &&
1680
 
                        clearBox.y2 () > clearBox.y1 ())
1681
 
                    {
1682
 
                        glPushAttrib (GL_SCISSOR_BIT);
1683
 
                        glEnable (GL_SCISSOR_TEST);
1684
 
                        glScissor (clearBox.x1 (),
1685
 
                                   screen->height () - clearBox.y2 (),
1686
 
                                   clearBox.width (),
1687
 
                                   clearBox.height ());
1688
 
                        glClear (GL_STENCIL_BUFFER_BIT);
1689
 
                        glPopAttrib ();
1690
 
                    }
1691
 
 
1692
 
                    glStencilFunc (GL_ALWAYS, 0x1, ~0);
1693
 
                    glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
1694
 
 
1695
 
                    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1696
 
                    gWindow->glDrawGeometry ();
1697
 
                    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1698
 
 
1699
 
                    glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1700
 
                    glDisable (GL_STENCIL_TEST);
1701
 
                }
1702
 
            }
1703
 
        }
1704
 
    }
1705
 
 
1706
 
    status = gWindow->glDraw (transform, attrib, region, mask);
1707
 
 
1708
 
    state[BLUR_STATE_CLIENT].active = false;
1709
 
    state[BLUR_STATE_DECOR].active  = false;
1710
 
 
1711
 
    return status;
1712
 
}
1713
 
 
1714
 
void
1715
 
BlurWindow::glDrawTexture (GLTexture          *texture,
1716
 
                           GLFragment::Attrib &attrib,
1717
 
                           unsigned int       mask)
1718
 
{
1719
 
    int state = BLUR_STATE_DECOR;
1720
 
 
1721
 
    foreach (GLTexture *tex, gWindow->textures ())
1722
 
        if (texture == tex)
1723
 
            state = BLUR_STATE_CLIENT;
1724
 
 
1725
 
    if (blur || this->state[state].active)
1726
 
    {
1727
 
        GLFragment::Attrib fa (attrib);
1728
 
        int                param, function;
1729
 
        int                unit = 0;
1730
 
        GLfloat            dx, dy;
1731
 
        int                iTC = 0;
1732
 
 
1733
 
        if (blur)
1734
 
        {
1735
 
            param = fa.allocParameters (1);
1736
 
 
1737
 
            function = bScreen->getSrcBlurFragmentFunction (texture, param);
1738
 
            if (function)
1739
 
            {
1740
 
                fa.addFunction (function);
1741
 
 
1742
 
                dx = ((texture->matrix ().xx / 2.1f) * blur) / 65535.0f;
1743
 
                dy = ((texture->matrix ().yy / 2.1f) * blur) / 65535.0f;
1744
 
 
1745
 
                (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1746
 
                                              param, dx, dy, dx, -dy);
1747
 
 
1748
 
                /* bi-linear filtering is required */
1749
 
                mask |= PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
1750
 
            }
1751
 
        }
1752
 
 
1753
 
        if (this->state[state].active)
1754
 
        {
1755
 
            GLFragment::Attrib dstFa (fa);
1756
 
            float              threshold = (float) this->state[state].threshold;
1757
 
 
1758
 
            switch (bScreen->opt[BLUR_OPTION_FILTER].value ().i ()) {
1759
 
                case BLUR_FILTER_4X_BILINEAR:
1760
 
                    dx = bScreen->tx / 2.1f;
1761
 
                    dy = bScreen->ty / 2.1f;
1762
 
 
1763
 
                    param = dstFa.allocParameters (3);
1764
 
                    unit  = dstFa.allocTextureUnits (1);
1765
 
 
1766
 
                    function = bScreen->getDstBlurFragmentFunction (
1767
 
                        texture, param, unit, 0, 0);
1768
 
                    if (function)
1769
 
                    {
1770
 
                        dstFa.addFunction (function);
1771
 
 
1772
 
                        (*GL::activeTexture) (GL_TEXTURE0_ARB + unit);
1773
 
                        glBindTexture (bScreen->target, bScreen->texture[0]);
1774
 
                        (*GL::activeTexture) (GL_TEXTURE0_ARB);
1775
 
 
1776
 
                        (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1777
 
                                                      param,
1778
 
                                                      bScreen->tx, bScreen->ty,
1779
 
                                                      0.0f, 0.0f);
1780
 
 
1781
 
                        (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1782
 
                                                      param + 1,
1783
 
                                                      threshold, threshold,
1784
 
                                                      threshold, threshold);
1785
 
 
1786
 
                        (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1787
 
                                                      param + 2,
1788
 
                                                      dx, dy, 0.0f, 0.0f);
1789
 
                    }
1790
 
                    break;
1791
 
                case BLUR_FILTER_GAUSSIAN:
1792
 
                    if (bScreen->opt[BLUR_OPTION_INDEPENDENT_TEX].value ().b ())
1793
 
                    {
1794
 
                        /* leave one free texture unit for fragment position */
1795
 
                        iTC = MAX (0, GL::maxTextureUnits -
1796
 
                                   (gWindow->geometry ().texUnits + 1));
1797
 
                        if (iTC)
1798
 
                            iTC = MIN (iTC / 2, bScreen->numTexop);
1799
 
                    }
1800
 
 
1801
 
                    param = dstFa.allocParameters (2);
1802
 
                    unit  = dstFa.allocTextureUnits (2);
1803
 
 
1804
 
                    function = bScreen->getDstBlurFragmentFunction (
1805
 
                        texture, param, unit, iTC, gWindow->geometry().texUnits);
1806
 
                    if (function)
1807
 
                    {
1808
 
                        int           i;
1809
 
 
1810
 
                        dstFa.addFunction (function);
1811
 
 
1812
 
                        (*GL::activeTexture) (GL_TEXTURE0_ARB + unit);
1813
 
                        glBindTexture (bScreen->target, bScreen->texture[0]);
1814
 
                        (*GL::activeTexture) (GL_TEXTURE0_ARB + unit + 1);
1815
 
                        glBindTexture (bScreen->target, bScreen->texture[1]);
1816
 
                        (*GL::activeTexture) (GL_TEXTURE0_ARB);
1817
 
 
1818
 
                        (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1819
 
                                                      param, bScreen->tx,
1820
 
                                                      bScreen->ty, 0.0f, 0.0f);
1821
 
 
1822
 
                        (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1823
 
                                                      param + 1,
1824
 
                                                      threshold, threshold,
1825
 
                                                      threshold, threshold);
1826
 
 
1827
 
                        if (iTC)
1828
 
                        {
1829
 
                            GLMatrix tm, rm;
1830
 
                            float s_gen[4], t_gen[4], q_gen[4];
1831
 
 
1832
 
                            for (i = 0; i < 16; i++)
1833
 
                                tm[i] = 0;
1834
 
                            tm[0] = (bScreen->output->width () / 2.0) *
1835
 
                                    bScreen->tx;
1836
 
                            tm[5] = (bScreen->output->height () / 2.0) *
1837
 
                                    bScreen->ty;
1838
 
                            tm[10] = 1;
1839
 
 
1840
 
                            tm[12] = (bScreen->output->width () / 2.0 +
1841
 
                                     bScreen->output->x1 ()) * bScreen->tx;
1842
 
                            tm[13] = (bScreen->output->height () / 2.0 +
1843
 
                                     screen->height () -
1844
 
                                     bScreen->output->y2 ()) * bScreen->ty;
1845
 
                            tm[14] = 1;
1846
 
                            tm[15] = 1;
1847
 
 
1848
 
                            tm *= bScreen->mvp;
1849
 
 
1850
 
                            for (i = 0; i < iTC; i++)
1851
 
                            {
1852
 
                                (*GL::activeTexture) (GL_TEXTURE0_ARB +
1853
 
                                    gWindow->geometry ().texUnits + (i * 2));
1854
 
 
1855
 
                                rm.reset ();
1856
 
                                rm[13] = bScreen->ty * bScreen->pos[i];
1857
 
                                rm *= tm;
1858
 
 
1859
 
                                s_gen[0] = rm[0];
1860
 
                                s_gen[1] = rm[4];
1861
 
                                s_gen[2] = rm[8];
1862
 
                                s_gen[3] = rm[12];
1863
 
                                t_gen[0] = rm[1];
1864
 
                                t_gen[1] = rm[5];
1865
 
                                t_gen[2] = rm[9];
1866
 
                                t_gen[3] = rm[13];
1867
 
                                q_gen[0] = rm[3];
1868
 
                                q_gen[1] = rm[7];
1869
 
                                q_gen[2] = rm[11];
1870
 
                                q_gen[3] = rm[15];
1871
 
 
1872
 
                                glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
1873
 
                                glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen);
1874
 
                                glTexGenfv(GL_Q, GL_OBJECT_PLANE, q_gen);
1875
 
 
1876
 
                                glTexGeni(GL_S, GL_TEXTURE_GEN_MODE,
1877
 
                                          GL_OBJECT_LINEAR);
1878
 
                                glTexGeni(GL_T, GL_TEXTURE_GEN_MODE,
1879
 
                                          GL_OBJECT_LINEAR);
1880
 
                                glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE,
1881
 
                                          GL_OBJECT_LINEAR);
1882
 
 
1883
 
                                glEnable(GL_TEXTURE_GEN_S);
1884
 
                                glEnable(GL_TEXTURE_GEN_T);
1885
 
                                glEnable(GL_TEXTURE_GEN_Q);
1886
 
 
1887
 
                                (*GL::activeTexture) (GL_TEXTURE0_ARB +
1888
 
                                    gWindow->geometry ().texUnits +
1889
 
                                    1 + (i * 2));
1890
 
 
1891
 
                                rm.reset ();
1892
 
                                
1893
 
                                rm[13] = -bScreen->ty * bScreen->pos[i];
1894
 
                                rm *= tm;
1895
 
                                
1896
 
                                s_gen[0] = rm[0];
1897
 
                                s_gen[1] = rm[4];
1898
 
                                s_gen[2] = rm[8];
1899
 
                                s_gen[3] = rm[12];
1900
 
                                t_gen[0] = rm[1];
1901
 
                                t_gen[1] = rm[5];
1902
 
                                t_gen[2] = rm[9];
1903
 
                                t_gen[3] = rm[13];
1904
 
                                q_gen[0] = rm[3];
1905
 
                                q_gen[1] = rm[7];
1906
 
                                q_gen[2] = rm[11];
1907
 
                                q_gen[3] = rm[15];
1908
 
 
1909
 
                                glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen);
1910
 
                                glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen);
1911
 
                                glTexGenfv(GL_Q, GL_OBJECT_PLANE, q_gen);
1912
 
 
1913
 
                                glTexGeni(GL_S, GL_TEXTURE_GEN_MODE,
1914
 
                                          GL_OBJECT_LINEAR);
1915
 
                                glTexGeni(GL_T, GL_TEXTURE_GEN_MODE,
1916
 
                                          GL_OBJECT_LINEAR);
1917
 
                                glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE,
1918
 
                                          GL_OBJECT_LINEAR);
1919
 
 
1920
 
                                glEnable(GL_TEXTURE_GEN_S);
1921
 
                                glEnable(GL_TEXTURE_GEN_T);
1922
 
                                glEnable(GL_TEXTURE_GEN_Q);
1923
 
                            }
1924
 
 
1925
 
                            (*GL::activeTexture) (GL_TEXTURE0_ARB);
1926
 
                        }
1927
 
 
1928
 
                    }
1929
 
                    break;
1930
 
                case BLUR_FILTER_MIPMAP:
1931
 
                    param = dstFa.allocParameters (2);
1932
 
                    unit  = dstFa.allocTextureUnits (1);
1933
 
 
1934
 
                    function =
1935
 
                        bScreen->getDstBlurFragmentFunction (texture, param,
1936
 
                                                             unit, 0, 0);
1937
 
                    if (function)
1938
 
                    {
1939
 
                        float lod =
1940
 
                            bScreen->opt[BLUR_OPTION_MIPMAP_LOD].value ().f ();
1941
 
 
1942
 
                        dstFa.addFunction (function);
1943
 
 
1944
 
                        (*GL::activeTexture) (GL_TEXTURE0_ARB + unit);
1945
 
                        glBindTexture (bScreen->target, bScreen->texture[0]);
1946
 
                        (*GL::activeTexture) (GL_TEXTURE0_ARB);
1947
 
 
1948
 
                        (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1949
 
                                                      param,
1950
 
                                                      bScreen->tx, bScreen->ty,
1951
 
                                                      0.0f, lod);
1952
 
 
1953
 
                        (*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1954
 
                                                      param + 1,
1955
 
                                                      threshold, threshold,
1956
 
                                                      threshold, threshold);
1957
 
                    }
1958
 
                    break;
1959
 
            }
1960
 
 
1961
 
            if (this->state[state].clipped ||
1962
 
                (!bScreen->blurOcclusion && !clip.isEmpty ()))
1963
 
            {
1964
 
                glEnable (GL_STENCIL_TEST);
1965
 
 
1966
 
                glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
1967
 
                glStencilFunc (GL_EQUAL, 0x1, ~0);
1968
 
 
1969
 
                /* draw region with destination blur */
1970
 
                gWindow->glDrawTexture (texture, dstFa, mask);
1971
 
 
1972
 
                glStencilFunc (GL_EQUAL, 0, ~0);
1973
 
 
1974
 
                /* draw region without destination blur */
1975
 
                gWindow->glDrawTexture (texture, fa, mask);
1976
 
 
1977
 
                glDisable (GL_STENCIL_TEST);
1978
 
            }
1979
 
            else
1980
 
            {
1981
 
                /* draw with destination blur */
1982
 
                gWindow->glDrawTexture (texture, dstFa, mask);
1983
 
            }
1984
 
        }
1985
 
        else
1986
 
        {
1987
 
            gWindow->glDrawTexture (texture, fa, mask);
1988
 
        }
1989
 
 
1990
 
        if (unit)
1991
 
        {
1992
 
            (*GL::activeTexture) (GL_TEXTURE0_ARB + unit);
1993
 
            glBindTexture (bScreen->target, 0);
1994
 
            (*GL::activeTexture) (GL_TEXTURE0_ARB + unit + 1);
1995
 
            glBindTexture (bScreen->target, 0);
1996
 
            (*GL::activeTexture) (GL_TEXTURE0_ARB);
1997
 
        }
1998
 
        
1999
 
        if (iTC)
2000
 
        {
2001
 
            int i;
2002
 
            for (i = gWindow->geometry().texUnits;
2003
 
                 i < gWindow->geometry().texUnits + (2 * iTC); i++)
2004
 
            {
2005
 
                (*GL::activeTexture) (GL_TEXTURE0_ARB + i);
2006
 
                glDisable(GL_TEXTURE_GEN_S);
2007
 
                glDisable(GL_TEXTURE_GEN_T);
2008
 
                glDisable(GL_TEXTURE_GEN_Q);
2009
 
            }
2010
 
            (*GL::activeTexture) (GL_TEXTURE0_ARB);
2011
 
        }
2012
 
    }
2013
 
    else
2014
 
    {
2015
 
        gWindow->glDrawTexture (texture, attrib, mask);
2016
 
    }
2017
 
}
2018
 
 
2019
 
void
2020
 
BlurScreen::handleEvent (XEvent *event)
2021
 
{
2022
 
    Window activeWindow = screen->activeWindow ();
2023
 
 
2024
 
    screen->handleEvent (event);
2025
 
 
2026
 
    if (screen->activeWindow () != activeWindow)
2027
 
    {
2028
 
        CompWindow *w;
2029
 
 
2030
 
        w = screen->findWindow (activeWindow);
2031
 
        if (w)
2032
 
        {
2033
 
            if (opt[BLUR_OPTION_FOCUS_BLUR].value ().b ())
2034
 
            {
2035
 
                CompositeWindow::get (w)->addDamage ();
2036
 
                moreBlur = true;
2037
 
            }
2038
 
        }
2039
 
 
2040
 
        w = screen->findWindow (screen->activeWindow ());
2041
 
        if (w)
2042
 
        {
2043
 
            if (opt[BLUR_OPTION_FOCUS_BLUR].value ().b ())
2044
 
            {
2045
 
                CompositeWindow::get (w)->addDamage ();
2046
 
                moreBlur = true;
2047
 
            }
2048
 
        }
2049
 
    }
2050
 
 
2051
 
    if (event->type == PropertyNotify)
2052
 
    {
2053
 
        int i;
2054
 
 
2055
 
        for (i = 0; i < BLUR_STATE_NUM; i++)
2056
 
        {
2057
 
            if (event->xproperty.atom == blurAtom[i])
2058
 
            {
2059
 
                CompWindow *w;
2060
 
 
2061
 
                w = screen->findWindow (event->xproperty.window);
2062
 
                if (w)
2063
 
                    BlurWindow::get (w)->update (i);
2064
 
            }
2065
 
        }
2066
 
    }
2067
 
}
2068
 
 
2069
 
void
2070
 
BlurWindow::resizeNotify (int dx,
2071
 
                          int dy,
2072
 
                          int dwidth,
2073
 
                          int dheight)
2074
 
{
2075
 
    if (bScreen->alphaBlur)
2076
 
    {
2077
 
        if (state[BLUR_STATE_CLIENT].threshold ||
2078
 
            state[BLUR_STATE_DECOR].threshold)
2079
 
            updateRegion ();
2080
 
    }
2081
 
 
2082
 
    window->resizeNotify (dx, dy, dwidth, dheight);
2083
 
 
2084
 
}
2085
 
 
2086
 
void
2087
 
BlurWindow::moveNotify (int  dx,
2088
 
                        int  dy,
2089
 
                        bool immediate)
2090
 
{
2091
 
    if (!region.isEmpty ())
2092
 
        region.translate (dx, dy);
2093
 
 
2094
 
    window->moveNotify (dx, dy, immediate);
2095
 
}
2096
 
 
2097
 
static bool
2098
 
blurPulse (CompAction         *action,
2099
 
           CompAction::State  state,
2100
 
           CompOption::Vector &options)
2101
 
{
2102
 
    CompWindow *w;
2103
 
    int        xid;
2104
 
 
2105
 
    xid = CompOption::getIntOptionNamed (options, "window",
2106
 
                                         screen->activeWindow ());
2107
 
 
2108
 
    w = screen->findWindow (xid);
2109
 
    if (w && GL::fragmentProgram)
2110
 
    {
2111
 
        BLUR_SCREEN (screen);
2112
 
        BLUR_WINDOW (w);
2113
 
 
2114
 
        bw->pulse    = TRUE;
2115
 
        bs->moreBlur = TRUE;
2116
 
 
2117
 
        bw->cWindow->addDamage ();
2118
 
    }
2119
 
 
2120
 
    return false;
2121
 
}
2122
 
 
2123
 
void
2124
 
BlurScreen::matchExpHandlerChanged ()
2125
 
{
2126
 
    screen->matchExpHandlerChanged ();
2127
 
 
2128
 
    /* match options are up to date after the call to matchExpHandlerChanged */
2129
 
    foreach (CompWindow *w, screen->windows ())
2130
 
        BlurWindow::get (w)->updateMatch ();
2131
 
 
2132
 
}
2133
 
 
2134
 
void
2135
 
BlurScreen::matchPropertyChanged (CompWindow *w)
2136
 
{
2137
 
    BlurWindow::get (w)->updateMatch ();
2138
 
 
2139
 
    screen->matchPropertyChanged (w);
2140
 
}
2141
 
 
2142
 
static CompMetadata *blurMetadata;
2143
 
 
2144
 
static const CompMetadata::OptionInfo blurOptionInfo[] = {
2145
 
    { "pulse", "bell", 0, blurPulse, 0 },
2146
 
    { "blur_speed", "float", "<min>0.1</min>", 0, 0 },
2147
 
    { "focus_blur_match", "match", 0, 0, 0 },
2148
 
    { "focus_blur", "bool", 0, 0, 0 },
2149
 
    { "alpha_blur_match", "match", 0, 0, 0 },
2150
 
    { "alpha_blur", "bool", 0, 0, 0 },
2151
 
    { "filter", "int", RESTOSTRING (0, BLUR_FILTER_LAST), 0, 0 },
2152
 
    { "gaussian_radius", "int", "<min>1</min><max>15</max>", 0, 0 },
2153
 
    { "gaussian_strength", "float", "<min>0.0</min><max>1.0</max>", 0, 0 },
2154
 
    { "mipmap_lod", "float", "<min>0.1</min><max>5.0</max>", 0, 0 },
2155
 
    { "saturation", "int", "<min>0</min><max>100</max>", 0, 0 },
2156
 
    { "occlusion", "bool", 0, 0, 0 },
2157
 
    { "independent_tex", "bool", 0, 0, 0 }
2158
 
};
2159
 
 
2160
 
CompOption::Vector &
2161
 
BlurScreen::getOptions ()
2162
 
{
2163
 
    return opt;
2164
 
}
2165
 
 
2166
 
bool
2167
 
BlurScreen::setOption (const char        *name,
2168
 
                       CompOption::Value &value)
2169
 
{
2170
 
    CompOption   *o;
2171
 
    unsigned int index;
2172
 
 
2173
 
    o = CompOption::findOption (opt, name, &index);
2174
 
    if (!o)
2175
 
        return false;
2176
 
 
2177
 
    switch (index) {
2178
 
        case BLUR_OPTION_BLUR_SPEED:
2179
 
            if (o->set (value))
2180
 
            {
2181
 
                blurTime = 1000.0f / o->value ().f ();
2182
 
                return true;
2183
 
            }
2184
 
            break;
2185
 
        case BLUR_OPTION_FOCUS_BLUR_MATCH:
2186
 
        case BLUR_OPTION_ALPHA_BLUR_MATCH:
2187
 
            if (o->set (value))
2188
 
            {
2189
 
                foreach (CompWindow *w, screen->windows ())
2190
 
                    BlurWindow::get (w)->updateMatch ();
2191
 
 
2192
 
                moreBlur = true;
2193
 
                cScreen->damageScreen ();
2194
 
 
2195
 
                return true;
2196
 
            }
2197
 
            break;
2198
 
        case BLUR_OPTION_FOCUS_BLUR:
2199
 
            if (o->set (value))
2200
 
            {
2201
 
                moreBlur = true;
2202
 
                cScreen->damageScreen ();
2203
 
 
2204
 
                return true;
2205
 
            }
2206
 
            break;
2207
 
        case BLUR_OPTION_ALPHA_BLUR:
2208
 
            if (o->set (value))
2209
 
            {
2210
 
                if (GL::fragmentProgram && o->value ().b ())
2211
 
                    alphaBlur = true;
2212
 
                else
2213
 
                    alphaBlur = false;
2214
 
 
2215
 
                cScreen->damageScreen ();
2216
 
 
2217
 
                return true;
2218
 
            }
2219
 
            break;
2220
 
        case BLUR_OPTION_FILTER:
2221
 
            if (o->set (value))
2222
 
            {
2223
 
                blurReset ();
2224
 
                cScreen->damageScreen ();
2225
 
                return true;
2226
 
            }
2227
 
            break;
2228
 
        case BLUR_OPTION_GAUSSIAN_RADIUS:
2229
 
        case BLUR_OPTION_GAUSSIAN_STRENGTH:
2230
 
        case BLUR_OPTION_INDEPENDENT_TEX:
2231
 
            if (o->set (value))
2232
 
            {
2233
 
                if (opt[BLUR_OPTION_FILTER].value ().i () == BLUR_FILTER_GAUSSIAN)
2234
 
                {
2235
 
                    blurReset ();
2236
 
                    cScreen->damageScreen ();
2237
 
                }
2238
 
                return true;
2239
 
            }
2240
 
            break;
2241
 
        case BLUR_OPTION_MIPMAP_LOD:
2242
 
            if (o->set (value))
2243
 
            {
2244
 
                if (opt[BLUR_OPTION_FILTER].value ().i () == BLUR_FILTER_MIPMAP)
2245
 
                {
2246
 
                    blurReset ();
2247
 
                    cScreen->damageScreen ();
2248
 
                }
2249
 
                return true;
2250
 
            }
2251
 
            break;
2252
 
        case BLUR_OPTION_SATURATION:
2253
 
            if (o->set (value))
2254
 
            {
2255
 
                blurReset ();
2256
 
                cScreen->damageScreen ();
2257
 
                return true;
2258
 
            }
2259
 
            break;
2260
 
        case BLUR_OPTION_BLUR_OCCLUSION:
2261
 
            if (o->set (value))
2262
 
            {
2263
 
                blurOcclusion = o->value ().b ();
2264
 
                blurReset ();
2265
 
                cScreen->damageScreen ();
2266
 
                return true;
2267
 
            }
2268
 
            break;
2269
 
        default:
2270
 
            return CompOption::setOption (*o, value);
2271
 
            break;
2272
 
    }
2273
 
 
2274
 
    return false;
2275
 
}
2276
 
 
2277
 
BlurScreen::BlurScreen (CompScreen *screen) :
2278
 
    PrivateHandler<BlurScreen,CompScreen> (screen),
2279
 
    cScreen (CompositeScreen::get (screen)),
2280
 
    gScreen (GLScreen::get (screen)),
2281
 
    opt(BLUR_OPTION_NUM),
2282
 
    moreBlur (false),
2283
 
    filterRadius (0),
2284
 
    srcBlurFunctions (0),
2285
 
    dstBlurFunctions (0),
2286
 
    output (NULL),
2287
 
    count (0),
2288
 
    program (0),
2289
 
    maxTemp (32),
2290
 
    fbo (0),
2291
 
    fboStatus (0)
2292
 
{
2293
 
    if (!blurVTable->getMetadata ()->initOptions (blurOptionInfo,
2294
 
                                                  BLUR_OPTION_NUM, opt))
2295
 
    {
2296
 
        setFailed ();
2297
 
        return;
2298
 
    }
2299
 
 
2300
 
    blurAtom[BLUR_STATE_CLIENT] =
2301
 
        XInternAtom (screen->dpy (), "_COMPIZ_WM_WINDOW_BLUR", 0);
2302
 
    blurAtom[BLUR_STATE_DECOR] =
2303
 
        XInternAtom (screen->dpy (), DECOR_BLUR_ATOM_NAME, 0);
2304
 
 
2305
 
    blurTime = 1000.0f / opt[BLUR_OPTION_BLUR_SPEED].value ().f ();
2306
 
    blurOcclusion = opt[BLUR_OPTION_BLUR_OCCLUSION].value ().b ();
2307
 
 
2308
 
    for (int i = 0; i < 2; i++)
2309
 
        texture[i] = 0;
2310
 
 
2311
 
    glGetIntegerv (GL_STENCIL_BITS, &stencilBits);
2312
 
    if (!stencilBits)
2313
 
        compLogMessage ("blur", CompLogLevelWarn,
2314
 
                        "No stencil buffer. Region based blur disabled");
2315
 
 
2316
 
    /* We need GL_ARB_fragment_program for blur */
2317
 
    if (GL::fragmentProgram)
2318
 
        alphaBlur = opt[BLUR_OPTION_ALPHA_BLUR].value ().b ();
2319
 
    else
2320
 
        alphaBlur = false;
2321
 
 
2322
 
    if (GL::fragmentProgram)
2323
 
    {
2324
 
        int tmp[4];
2325
 
        GL::getProgramiv (GL_FRAGMENT_PROGRAM_ARB,
2326
 
                          GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,
2327
 
                          tmp);
2328
 
        maxTemp = tmp[0];
2329
 
    }
2330
 
 
2331
 
    updateFilterRadius ();
2332
 
 
2333
 
    ScreenInterface::setHandler (screen, true);
2334
 
    CompositeScreenInterface::setHandler (cScreen, true);
2335
 
    GLScreenInterface::setHandler (gScreen, true);
2336
 
}
2337
 
 
2338
 
 
2339
 
BlurScreen::~BlurScreen ()
2340
 
{
2341
 
    foreach (BlurFunction &bf, srcBlurFunctions)
2342
 
        GLFragment::destroyFragmentFunction (bf.id);
2343
 
    foreach (BlurFunction &bf, dstBlurFunctions)
2344
 
        GLFragment::destroyFragmentFunction (bf.id);
2345
 
 
2346
 
    cScreen->damageScreen ();
2347
 
 
2348
 
    if (fbo)
2349
 
        (*GL::deleteFramebuffers) (1, &fbo);
2350
 
 
2351
 
    for (int i = 0; i < 2; i++)
2352
 
        if (texture[i])
2353
 
            glDeleteTextures (1, &texture[i]);
2354
 
 
2355
 
}
2356
 
 
2357
 
BlurWindow::BlurWindow (CompWindow *w) :
2358
 
    PrivateHandler<BlurWindow,CompWindow> (w),
2359
 
    window (w),
2360
 
    gWindow (GLWindow::get (w)),
2361
 
    cWindow (CompositeWindow::get (w)),
2362
 
    bScreen (BlurScreen::get (screen)),
2363
 
    blur (0),
2364
 
    pulse (false),
2365
 
    focusBlur (false)
2366
 
{
2367
 
    for (int i = 0; i < BLUR_STATE_NUM; i++)
2368
 
    {
2369
 
        state[i].threshold = 0;
2370
 
        state[i].clipped   = false;
2371
 
        state[i].active    = false;
2372
 
 
2373
 
        propSet[i] = false;
2374
 
    }
2375
 
 
2376
 
    update (BLUR_STATE_CLIENT);
2377
 
    update (BLUR_STATE_DECOR);
2378
 
 
2379
 
    updateMatch ();
2380
 
 
2381
 
 
2382
 
    WindowInterface::setHandler (window, true);
2383
 
    GLWindowInterface::setHandler (gWindow, true);
2384
 
}
2385
 
 
2386
 
BlurWindow::~BlurWindow ()
2387
 
{
2388
 
}
2389
 
 
2390
 
bool
2391
 
BlurPluginVTable::init ()
2392
 
{
2393
 
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) |
2394
 
        !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) |
2395
 
        !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
2396
 
         return false;
2397
 
 
2398
 
    getMetadata ()->addFromOptionInfo (blurOptionInfo, BLUR_OPTION_NUM);
2399
 
    getMetadata ()->addFromFile (name ());
2400
 
 
2401
 
    return true;
2402
 
}
2403