2
* Copyright © 2007 Novell, Inc.
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
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.
23
* Author: David Reveman <davidr@novell.com>
28
COMPIZ_PLUGIN_20081216 (blur, BlurPluginVTable)
30
/* pascal triangle based kernel generator */
32
blurCreateGaussianLinearKernel (int radius,
38
float factor = 0.5f + (strength / 2.0f);
39
float buffer1[BLUR_GAUSSIAN_RADIUS_MAX * 3];
40
float buffer2[BLUR_GAUSSIAN_RADIUS_MAX * 3];
45
int size = (radius * 2) + 1;
46
int mySize = ceil (radius / 2.0f);
52
for (i = 3; i <= size; i++)
56
for (j = 1; j < i - 1; j++)
57
ar2[j] = (ar1[j - 1] + ar1[j]) * factor;
67
for (i = 0; i < size; i++)
73
for (i = 0; i < size; i++)
87
for (; i < mySize; i++)
90
pos[i] -= ar1[j + 1] / (ar1[j] + ar1[j + 1]);
91
amp[i] = ar1[j] + ar1[j + 1];
97
amp[mySize] = ar1[radius];
105
BlurScreen::updateFilterRadius ()
108
switch (opt[BLUR_OPTION_FILTER].value ().i ()) {
109
case BLUR_FILTER_4X_BILINEAR:
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 ();
116
blurCreateGaussianLinearKernel (radius, strength, amp, pos,
119
filterRadius = radius;
121
case BLUR_FILTER_MIPMAP: {
122
float lod = opt[BLUR_OPTION_MIPMAP_LOD].value ().f ();
124
filterRadius = powf (2.0f, ceilf (lod));
131
BlurScreen::blurReset ()
133
updateFilterRadius ();
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 ();
146
GL::deletePrograms (1, &program);
152
regionFromBoxes (std::vector<BlurBox> boxes,
159
foreach (BlurBox &box, boxes)
161
decor_apply_gravity (box.p1.gravity, box.p1.x, box.p1.y,
166
decor_apply_gravity (box.p2.gravity, box.p2.x, box.p2.y,
170
if (x2 > x1 && y2 > y1)
171
region += CompRect (x1, y1, x2 - x1, y2 - y1);
178
BlurWindow::updateRegion ()
182
if (state[BLUR_STATE_DECOR].threshold)
184
region += CompRect (-window->output ().left,
185
-window->output ().top,
186
window->width () + window->output ().right,
187
window->height () + window->output ().bottom);
189
region -= CompRect (0, 0, window->width (), window->height ());
191
state[BLUR_STATE_DECOR].clipped = false;
193
if (!state[BLUR_STATE_DECOR].box.empty ())
195
CompRegion q = regionFromBoxes (state[BLUR_STATE_DECOR].box,
204
state[BLUR_STATE_DECOR].clipped = true;
210
if (state[BLUR_STATE_CLIENT].threshold)
212
CompRegion r (0, 0, window->width (), window->height ());
214
state[BLUR_STATE_CLIENT].clipped = false;
216
if (!state[BLUR_STATE_CLIENT].box.empty ())
218
CompRegion q = regionFromBoxes (state[BLUR_STATE_CLIENT].box,
226
state[BLUR_STATE_CLIENT].clipped = true;
237
this->region = region;
238
if (!region.isEmpty ())
239
this->region.translate (window->x (), window->y ());
243
BlurWindow::setBlur (int state,
245
std::vector<BlurBox> box)
248
this->state[state].threshold = threshold;
249
this->state[state].box = box;
253
cWindow->addDamage ();
257
BlurWindow::updateAlphaMatch ()
259
if (!propSet[BLUR_STATE_CLIENT])
263
match = &bScreen->opt[BLUR_OPTION_ALPHA_BLUR_MATCH].value ().match ();
264
if (match->evaluate (window))
266
if (!state[BLUR_STATE_CLIENT].threshold)
267
setBlur (BLUR_STATE_CLIENT, 4, std::vector<BlurBox> ());
271
if (state[BLUR_STATE_CLIENT].threshold)
272
setBlur (BLUR_STATE_CLIENT, 0, std::vector<BlurBox> ());
278
BlurWindow::updateMatch ()
285
match = &bScreen->opt[BLUR_OPTION_FOCUS_BLUR_MATCH].value ().match ();
287
focus = GL::fragmentProgram && match->evaluate (window);
288
if (focus != focusBlur)
291
cWindow->addDamage ();
298
BlurWindow::update (int state)
302
unsigned long n, left;
303
unsigned char *propData;
305
std::vector<BlurBox> boxes;
307
result = XGetWindowProperty (screen->dpy (), window->id (),
308
bScreen->blurAtom[state], 0L, 8192L, FALSE,
309
XA_INTEGER, &actual, &format,
310
&n, &left, &propData);
312
if (result == Success && n && propData)
314
propSet[state] = true;
318
long *data = (long *) propData;
329
for (i = 0; i < (n - 2) / 6; i++)
331
box.p1.gravity = *data++;
334
box.p2.gravity = *data++;
338
boxes.push_back (box);
348
propSet[state] = false;
351
setBlur (state, threshold, boxes);
357
BlurScreen::preparePaint (int msSinceLastPaint)
362
bool focus = opt[BLUR_OPTION_FOCUS_BLUR].value ().b ();
365
steps = (msSinceLastPaint * 0xffff) / blurTime;
371
foreach (CompWindow *w, screen->windows ())
375
focusBlur = bw->focusBlur && focus;
378
(!focusBlur || w->id () == screen->activeWindow ()))
391
if (bw->blur < 0xffff)
395
bw->blur += steps * 2;
397
if (bw->blur >= 0xffff)
399
bw->blur = 0xffff - 1;
408
if (bw->blur < 0xffff)
418
cScreen->preparePaint (msSinceLastPaint);
420
if (cScreen->damageMask () & COMPOSITE_SCREEN_DAMAGE_REGION_MASK)
422
/* walk from bottom to top and expand damage */
427
CompRegion damage (cScreen->currentDamage ());
429
foreach (CompWindow *w, screen->windows ())
433
if (!w->isViewable () || !CompositeWindow::get (w)->damaged ())
436
if (!bw->region.isEmpty ())
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;
450
damage.shrink (-filterRadius, -filterRadius);
457
cScreen->damageRegion (damage);
465
BlurScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib,
466
const GLMatrix &transform, const CompRegion ®ion,
467
CompOutput *output, unsigned int mask)
473
stencilBox = region.boundingRect ();
474
this->region = region;
476
if (mask & PAINT_SCREEN_REGION_MASK)
478
/* we need to redraw more than the screen region being updated */
481
this->region.shrink (-filterRadius * 2, -filterRadius * 2);
483
this->region &= screen->region ();
490
occlusion = CompRegion ();
492
foreach (CompWindow *w, screen->windows ())
493
BlurWindow::get (w)->clip = CompRegion ();
496
this->output = output;
499
status = gScreen->glPaintOutput (sAttrib, transform, this->region, output, mask);
501
status = gScreen->glPaintOutput (sAttrib, transform, region, output, mask);
507
BlurScreen::glPaintTransformedOutput (const GLScreenPaintAttrib &sAttrib,
508
const GLMatrix &transform,
509
const CompRegion ®ion,
510
CompOutput *output, unsigned int mask)
514
occlusion = CompRegion ();
516
foreach (CompWindow *w, screen->windows ())
517
BlurWindow::get (w)->clip = CompRegion ();
520
gScreen->glPaintTransformedOutput (sAttrib, transform, region, output, mask);
524
BlurScreen::donePaint ()
528
foreach (CompWindow *w, screen->windows ())
532
if (bw->blur > 0 && bw->blur < 0xffff)
533
bw->cWindow->addDamage ();
537
cScreen->donePaint ();
541
BlurWindow::glPaint (const GLWindowPaintAttrib &attrib,
542
const GLMatrix &transform,
543
const CompRegion ®ion, unsigned int mask)
546
bool status = gWindow->glPaint (attrib, transform, region, mask);
548
if (!bScreen->blurOcclusion &&
549
(mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK))
551
clip = bScreen->occlusion;
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;
562
GLFragment::FunctionId
563
BlurScreen::getSrcBlurFragmentFunction (GLTexture *texture,
566
GLFragment::FunctionData data;
567
BlurFunction function;
570
if (texture->target () == GL_TEXTURE_2D)
571
target = COMP_FETCH_TARGET_2D;
573
target = COMP_FETCH_TARGET_RECT;
575
foreach (BlurFunction &bf, srcBlurFunctions)
576
if (bf.param == param && bf.target == target)
581
static const char *temp[] = { "offset0", "offset1", "sum" };
584
for (i = 0; i < sizeof (temp) / sizeof (temp[0]); i++)
585
data.addTempHeaderOp (temp[i]);
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 };",
593
switch (opt[BLUR_OPTION_FILTER].value ().i ()) {
594
case BLUR_FILTER_4X_BILINEAR:
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;");
610
function.id = data.createFragmentFunction ("blur");
611
function.target = target;
612
function.param = param;
615
srcBlurFunctions.push_back (function);
623
GLFragment::FunctionId
624
BlurScreen::getDstBlurFragmentFunction (GLTexture *texture,
630
BlurFunction function;
631
GLFragment::FunctionData data;
635
if (texture->target () == GL_TEXTURE_2D)
637
target = COMP_FETCH_TARGET_2D;
638
targetString = (char *) "2D";
642
target = COMP_FETCH_TARGET_RECT;
643
targetString = (char *) "RECT";
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)
656
static const char *temp[] = { "fCoord", "mask", "sum", "dst" };
659
int saturation = opt[BLUR_OPTION_SATURATION].value ().i ();
662
int base, end, ITCbase;
664
for (i = 0; i < sizeof (temp) / sizeof (temp[0]); i++)
665
data.addTempHeaderOp (temp[i]);
667
if (saturation < 100)
668
data.addTempHeaderOp ("sat");
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"
677
for (i = 0; i < sizeof (filterTemp) / sizeof (filterTemp[0]); i++)
678
data.addTempHeaderOp (filterTemp[i]);
680
data.addFetchOp ("output", NULL, target);
681
data.addColorOp ("output", "output");
684
"MUL fCoord, fragment.position, program.env[%d];",
689
"ADD t0, fCoord, program.env[%d];"
690
"TEX s0, t0, texture[%d], %s;"
692
"SUB t1, fCoord, program.env[%d];"
693
"TEX s1, t1, texture[%d], %s;"
695
"MAD t2, program.env[%d], { -1.0, 1.0, 0.0, 0.0 }, fCoord;"
696
"TEX s2, t2, texture[%d], %s;"
698
"MAD t3, program.env[%d], { 1.0, -1.0, 0.0, 0.0 }, fCoord;"
699
"TEX s3, t3, texture[%d], %s;"
701
"MUL_SAT mask, output.a, program.env[%d];"
704
"MAD sum, s1, 0.25, sum;"
705
"MAD sum, s2, 0.25, sum;"
706
"MAD sum, s3, 0.25, sum;",
708
param + 2, unit, targetString,
709
param + 2, unit, targetString,
710
param + 2, unit, targetString,
711
param + 2, unit, targetString,
715
case BLUR_FILTER_GAUSSIAN: {
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)
723
numIndirectOp = numTexop;
727
i = MAX(((maxTemp / 2) - 4) / 4, 1);
728
numIndirect = ceil ((float)numTexop / (float)i);
729
numIndirectOp = ceil ((float)numTexop / (float)numIndirect);
732
/* we need to define all coordinate temporaries if we have
733
multiple indirection steps */
734
j = (numIndirect > 1) ? 0 : numITC;
736
for (i = 0; i < numIndirectOp * 2; i++)
738
snprintf (str, 1024, "pix_%d", i);
739
data.addTempHeaderOp (str);
742
for (i = j * 2; i < numIndirectOp * 2; i++)
744
snprintf (str, 1024, "coord_%d", i);
745
data.addTempHeaderOp (str);
749
data.addFetchOp ("output", NULL, target);
750
data.addColorOp ("output", "output");
753
"MUL fCoord, fragment.position, program.env[%d];",
757
data.addDataOp ("TEX sum, fCoord, texture[%d], %s;",
758
unit + 1, targetString);
761
data.addDataOp ("MUL_SAT mask, output.a, program.env[%d];"
763
param + 1, amp[numTexop]);
765
for (j = 0; j < numIndirect; j++)
767
base = j * numIndirectOp;
768
end = MIN ((j + 1) * numIndirectOp, numTexop) - base;
770
ITCbase = MAX (numITC - base, 0);
772
for (i = ITCbase; i < end; i++)
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);
781
for (i = 0; i < ITCbase; i++)
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);
792
for (i = ITCbase; i < end; i++)
795
"TEX pix_%d, coord_%d, texture[%d], %s;"
796
"TEX pix_%d, coord_%d, texture[%d], %s;",
798
unit + 1, targetString,
799
(i * 2) + 1, (i * 2) + 1,
800
unit + 1, targetString);
803
for (i = 0; i < end * 2; i++)
806
"MAD sum, pix_%d, %f, sum;",
807
i, amp[base + (i / 2)]);
812
case BLUR_FILTER_MIPMAP:
813
data.addFetchOp ("output", NULL, target);
814
data.addColorOp ("output", "output");
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,
827
if (saturation < 100)
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);
838
"MAD dst, mask, -output.a, mask;"
839
"MAD output.rgb, sum, dst.a, output;"
840
"ADD output.a, output.a, dst.a;");
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;
856
dstBlurFunctions.push_back (function);
865
BlurScreen::projectVertices (CompOutput *output,
866
const GLMatrix &transform,
871
GLdouble dProjection[16];
877
viewport[0] = output->x1 ();
878
viewport[1] = screen->height () - output->y2 ();
879
viewport[2] = output->width ();
880
viewport[3] = output->height ();
882
for (i = 0; i < 16; i++)
884
dModel[i] = transform.getMatrix ()[i];
885
dProjection[i] = gScreen->projectionMatrix ()[i];
890
if (!gluProject (object[0], object[1], object[2],
891
dModel, dProjection, viewport,
906
BlurScreen::loadFragmentProgram (GLuint *program,
915
(*GL::genPrograms) (1, program);
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);
922
glGetIntegerv (GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
923
if (glGetError () != GL_NO_ERROR || errorPos != -1)
925
compLogMessage ("blur", CompLogLevelError,
926
"Failed to load blur program %s", string);
928
(*GL::deletePrograms) (1, program);
938
BlurScreen::loadFilterProgram (int numITC)
946
int base, end, ITCbase;
948
if (target == GL_TEXTURE_2D)
949
targetString = (char *) "2D";
951
targetString = (char *) "RECT";
955
"ATTRIB texcoord = fragment.texcoord[0];"
958
if (maxTemp - 1 > (numTexop + (numTexop - numITC)) * 2)
961
numIndirectOp = numTexop;
965
i = (maxTemp - 1) / 4;
966
numIndirect = ceil ((float)numTexop / (float)i);
967
numIndirectOp = ceil ((float)numTexop / (float)numIndirect);
970
/* we need to define all coordinate temporaries if we have
971
multiple indirection steps */
972
j = (numIndirect > 1) ? 0 : numITC;
974
for (i = 0; i < numIndirectOp; i++)
975
str += sprintf (str,"TEMP pix_%d, pix_%d;", i * 2, (i * 2) + 1);
977
for (i = j; i < numIndirectOp; i++)
978
str += sprintf (str,"TEMP coord_%d, coord_%d;", i * 2, (i * 2) + 1);
981
"TEX sum, texcoord, texture[0], %s;",
988
for (j = 0; j < numIndirect; j++)
990
base = j * numIndirectOp;
991
end = MIN ((j + 1) * numIndirectOp, numTexop) - base;
993
ITCbase = MAX (numITC - base, 0);
995
for (i = ITCbase; i < end; i++)
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);
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);
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);
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)]);
1022
str += sprintf (str,
1023
"MOV result.color, sum;"
1026
return loadFragmentProgram (&program, buffer);
1030
BlurScreen::fboPrologue ()
1035
(*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, fbo);
1037
/* bind texture and check status the first time */
1040
(*GL::framebufferTexture2D) (GL_FRAMEBUFFER_EXT,
1041
GL_COLOR_ATTACHMENT0_EXT,
1045
fboStatus = (*GL::checkFramebufferStatus) (GL_FRAMEBUFFER_EXT);
1046
if (fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT)
1048
compLogMessage ("blur", CompLogLevelError,
1049
"Framebuffer incomplete");
1051
(*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
1052
(*GL::deleteFramebuffers) (1, &fbo);
1060
glPushAttrib (GL_VIEWPORT_BIT | GL_ENABLE_BIT);
1062
glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
1063
glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
1065
glDisable (GL_CLIP_PLANE0);
1066
glDisable (GL_CLIP_PLANE1);
1067
glDisable (GL_CLIP_PLANE2);
1068
glDisable (GL_CLIP_PLANE3);
1070
glViewport (0, 0, width, height);
1071
glMatrixMode (GL_PROJECTION);
1074
glOrtho (0.0, width, 0.0, height, -1.0, 1.0);
1075
glMatrixMode (GL_MODELVIEW);
1083
BlurScreen::fboEpilogue ()
1085
(*GL::bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
1087
glMatrixMode (GL_PROJECTION);
1089
glMatrixMode (GL_MODELVIEW);
1091
glDepthRange (0, 1);
1092
glViewport (-1, -1, 2, 2);
1093
glRasterPos2f (0, 0);
1095
gScreen->resetRasterPos ();
1097
glMatrixMode (GL_PROJECTION);
1099
glMatrixMode (GL_MODELVIEW);
1102
glDrawBuffer (GL_BACK);
1103
glReadBuffer (GL_BACK);
1109
BlurScreen::fboUpdate (BoxPtr pBox,
1113
Bool wasCulled = glIsEnabled (GL_CULL_FACE);
1115
if (GL::maxTextureUnits &&
1116
opt[BLUR_OPTION_INDEPENDENT_TEX].value ().b ())
1117
iTC = MIN ((GL::maxTextureUnits - 1) / 2, numTexop);
1120
if (!loadFilterProgram (iTC))
1123
if (!fboPrologue ())
1126
glDisable (GL_CULL_FACE);
1128
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1130
glBindTexture (target, texture[0]);
1132
glEnable (GL_FRAGMENT_PROGRAM_ARB);
1133
(*GL::bindProgram) (GL_FRAGMENT_PROGRAM_ARB, program);
1139
y = screen->height () - pBox->y2;
1141
for (i = 0; i < iTC; i++)
1143
(*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1144
tx * (pBox->x1 + pos[i]),
1146
(*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1147
tx * (pBox->x1 - pos[i]),
1151
glTexCoord2f (tx * pBox->x1, ty * y);
1152
glVertex2i (pBox->x1, y);
1154
for (i = 0; i < iTC; i++)
1156
(*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1157
tx * (pBox->x2 + pos[i]),
1159
(*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1160
tx * (pBox->x2 - pos[i]),
1164
glTexCoord2f (tx * pBox->x2, ty * y);
1165
glVertex2i (pBox->x2, y);
1167
y = screen->height () - pBox->y1;
1169
for (i = 0; i < iTC; i++)
1171
(*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1172
tx * (pBox->x2 + pos[i]),
1174
(*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1175
tx * (pBox->x2 - pos[i]),
1179
glTexCoord2f (tx * pBox->x2, ty * y);
1180
glVertex2i (pBox->x2, y);
1182
for (i = 0; i < iTC; i++)
1184
(*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2),
1185
tx * (pBox->x1 + pos[i]),
1187
(*GL::multiTexCoord2f) (GL_TEXTURE1_ARB + (i * 2) + 1,
1188
tx * (pBox->x1 - pos[i]),
1192
glTexCoord2f (tx * pBox->x1, ty * y);
1193
glVertex2i (pBox->x1, y);
1200
glDisable (GL_FRAGMENT_PROGRAM_ARB);
1202
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1205
glEnable (GL_CULL_FACE);
1212
#define MAX_VERTEX_PROJECT_COUNT 20
1215
BlurWindow::projectRegion (CompOutput *output,
1216
const GLMatrix &transform)
1218
float scrv[MAX_VERTEX_PROJECT_COUNT * 2];
1219
float vertices[MAX_VERTEX_PROJECT_COUNT * 3];
1220
int nVertices, nQuadCombine;
1223
float minX, maxX, minY, maxY, minZ, maxZ;
1226
GLTexture::MatrixList ml;
1227
GLWindow::Geometry *gm;
1229
gWindow->geometry ().reset ();
1230
gWindow->glAddGeometry (ml, bScreen->tmpRegion2, infiniteRegion);
1232
if (!gWindow->geometry ().vCount)
1235
gm = &gWindow->geometry ();
1237
nVertices = (gm->indexCount) ? gm->indexCount: gm->vCount;
1240
stride = gm->vertexStride;
1241
vert = gm->vertices + (stride - 3);
1243
/* we need to find the best value here */
1244
if (nVertices <= MAX_VERTEX_PROJECT_COUNT)
1246
for (i = 0; i < nVertices; i++)
1250
v = vert + (stride * gm->indices[i]);
1254
v = vert + (stride * i);
1257
vertices[i * 3] = v[0];
1258
vertices[(i * 3) + 1] = v[1];
1259
vertices[(i * 3) + 2] = v[2];
1264
minX = screen->width ();
1266
minY = screen->height ();
1271
for (i = 0; i < gm->vCount; i++)
1273
v = vert + (stride * i);
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;
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;
1315
if (!bScreen->projectVertices (output, transform, vertices, scrv,
1316
nVertices * nQuadCombine))
1319
for (i = 0; i < nVertices / 4; i++)
1321
scr = scrv + (i * 4 * 2);
1323
minX = screen->width ();
1325
minY = screen->height ();
1328
for (j = 0; j < 8 * nQuadCombine; j += 2)
1336
if (scr[j + 1] < minY)
1339
if (scr[j + 1] > maxY)
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;
1351
bScreen->tmpRegion3 += CompRect (x1, y1, x2 - x1, y2 - y1);
1357
BlurWindow::updateDstTexture (const GLMatrix &transform,
1359
int clientThreshold)
1364
filter = bScreen->opt[BLUR_OPTION_FILTER].value ().i ();
1366
bScreen->tmpRegion3 = CompRegion ();
1368
if (filter == BLUR_FILTER_GAUSSIAN)
1371
if (state[BLUR_STATE_DECOR].threshold)
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;
1380
bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1381
CompRect (xx, yy, ww, hh));
1383
if (!bScreen->tmpRegion2.isEmpty ())
1384
projectRegion (bScreen->output, transform);
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;
1392
bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1393
CompRect (xx, yy, ww, hh));
1395
if (!bScreen->tmpRegion2.isEmpty ())
1396
projectRegion (bScreen->output, transform);
1399
xx = window->x () - window->output ().left;
1401
ww = window->output ().left;
1402
hh = window->height ();
1404
bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1405
CompRect (xx, yy, ww, hh));
1407
if (!bScreen->tmpRegion2.isEmpty ())
1408
projectRegion (bScreen->output, transform);
1411
xx = window->x () + window->width ();
1413
ww = window->output ().right;
1414
hh = window->height ();
1416
bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1417
CompRect (xx, yy, ww, hh));
1419
if (!bScreen->tmpRegion2.isEmpty ())
1420
projectRegion (bScreen->output, transform);
1423
if (clientThreshold)
1426
bScreen->tmpRegion2 = bScreen->tmpRegion.intersected (
1427
CompRect (window->x (),
1430
window->height ()));
1432
if (!bScreen->tmpRegion2.isEmpty ())
1433
projectRegion (bScreen->output, transform);
1439
bScreen->tmpRegion2 = bScreen->tmpRegion;
1441
if (!bScreen->tmpRegion2.isEmpty ())
1442
projectRegion (bScreen->output, transform);
1445
bScreen->tmpRegion = bScreen->region.intersected (bScreen->tmpRegion3);
1447
if (bScreen->tmpRegion.isEmpty ())
1450
*pExtents = bScreen->tmpRegion.boundingRect ();
1452
if (!bScreen->texture[0] || bScreen->width != screen->width () ||
1453
bScreen->height != screen->height ())
1455
int i, textures = 1;
1457
bScreen->width = screen->width ();
1458
bScreen->height = screen->height ();
1460
if (GL::textureNonPowerOfTwo ||
1461
(POWER_OF_TWO (bScreen->width) && POWER_OF_TWO (bScreen->height)))
1463
bScreen->target = GL_TEXTURE_2D;
1464
bScreen->tx = 1.0f / bScreen->width;
1465
bScreen->ty = 1.0f / bScreen->height;
1469
bScreen->target = GL_TEXTURE_RECTANGLE_NV;
1474
if (filter == BLUR_FILTER_GAUSSIAN)
1476
if (GL::fbo && !bScreen->fbo)
1477
(*GL::genFramebuffers) (1, &bScreen->fbo);
1480
compLogMessage ("blur", CompLogLevelError,
1481
"Failed to create framebuffer object");
1486
bScreen->fboStatus = FALSE;
1488
for (i = 0; i < textures; i++)
1490
if (!bScreen->texture[i])
1491
glGenTextures (1, &bScreen->texture[i]);
1493
glBindTexture (bScreen->target, bScreen->texture[i]);
1495
glTexImage2D (bScreen->target, 0, GL_RGB,
1500
#if IMAGE_BYTE_ORDER == MSBFirst
1501
GL_UNSIGNED_INT_8_8_8_8_REV,
1508
glTexParameteri (bScreen->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1509
glTexParameteri (bScreen->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1511
if (filter == BLUR_FILTER_MIPMAP)
1515
compLogMessage ("blur", CompLogLevelWarn,
1516
"GL_EXT_framebuffer_object extension "
1517
"is required for mipmap filter");
1519
else if (bScreen->target != GL_TEXTURE_2D)
1521
compLogMessage ("blur", CompLogLevelWarn,
1522
"GL_ARB_texture_non_power_of_two "
1523
"extension is required for mipmap filter");
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);
1534
glTexParameteri (bScreen->target, GL_TEXTURE_WRAP_S,
1536
glTexParameteri (bScreen->target, GL_TEXTURE_WRAP_T,
1539
glCopyTexSubImage2D (bScreen->target, 0, 0, 0, 0, 0,
1540
bScreen->width, bScreen->height);
1545
glBindTexture (bScreen->target, bScreen->texture[0]);
1547
CompRect br = bScreen->tmpRegion.boundingRect ();
1549
y = screen->height () - br.y2 ();
1551
glCopyTexSubImage2D (bScreen->target, 0,
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);
1565
case BLUR_FILTER_4X_BILINEAR:
1569
glBindTexture (bScreen->target, 0);
1575
BlurWindow::glDraw (const GLMatrix &transform,
1576
GLFragment::Attrib &attrib,
1577
const CompRegion ®ion,
1582
if (bScreen->alphaBlur && !region.isEmpty ())
1584
int clientThreshold;
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;
1590
clientThreshold = 0;
1592
if (state[BLUR_STATE_DECOR].threshold || clientThreshold)
1594
bool clipped = FALSE;
1595
CompRect box (0, 0, 0, 0);
1599
bScreen->mvp = GLMatrix (bScreen->gScreen->projectionMatrix ());
1600
bScreen->mvp *= transform;
1602
if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
1603
reg = infiniteRegion;
1607
bScreen->tmpRegion = this->region.intersected (reg);
1608
if (!bScreen->blurOcclusion &&
1609
!(mask & PAINT_WINDOW_TRANSFORMED_MASK))
1610
bScreen->tmpRegion -= clip;
1612
if (updateDstTexture (transform, &box, clientThreshold))
1614
if (clientThreshold)
1616
if (state[BLUR_STATE_CLIENT].clipped)
1618
if (bScreen->stencilBits)
1620
state[BLUR_STATE_CLIENT].active = true;
1626
state[BLUR_STATE_CLIENT].active = true;
1630
if (state[BLUR_STATE_DECOR].threshold)
1632
if (state[BLUR_STATE_DECOR].clipped)
1634
if (bScreen->stencilBits)
1636
state[BLUR_STATE_DECOR].active = true;
1642
state[BLUR_STATE_DECOR].active = true;
1646
if (!bScreen->blurOcclusion && !clip.isEmpty ())
1650
if (!bScreen->blurOcclusion)
1651
bScreen->tmpRegion = this->region - clip;
1653
bScreen->tmpRegion = this->region;
1655
if (!clientThreshold)
1657
bScreen->tmpRegion -= CompRect (window->x (),
1658
window->x () + window->width (),
1660
window->y () + window->height ());
1665
GLTexture::MatrixList ml;
1667
gWindow->geometry ().reset ();
1669
gWindow->glAddGeometry (ml, bScreen->tmpRegion, reg);
1670
if (gWindow->geometry ().vCount)
1672
CompRect clearBox = bScreen->stencilBox;
1674
bScreen->stencilBox = box;
1676
glEnable (GL_STENCIL_TEST);
1677
glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1679
if (clearBox.x2 () > clearBox.x1 () &&
1680
clearBox.y2 () > clearBox.y1 ())
1682
glPushAttrib (GL_SCISSOR_BIT);
1683
glEnable (GL_SCISSOR_TEST);
1684
glScissor (clearBox.x1 (),
1685
screen->height () - clearBox.y2 (),
1687
clearBox.height ());
1688
glClear (GL_STENCIL_BUFFER_BIT);
1692
glStencilFunc (GL_ALWAYS, 0x1, ~0);
1693
glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE);
1695
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1696
gWindow->glDrawGeometry ();
1697
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1699
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1700
glDisable (GL_STENCIL_TEST);
1706
status = gWindow->glDraw (transform, attrib, region, mask);
1708
state[BLUR_STATE_CLIENT].active = false;
1709
state[BLUR_STATE_DECOR].active = false;
1715
BlurWindow::glDrawTexture (GLTexture *texture,
1716
GLFragment::Attrib &attrib,
1719
int state = BLUR_STATE_DECOR;
1721
foreach (GLTexture *tex, gWindow->textures ())
1723
state = BLUR_STATE_CLIENT;
1725
if (blur || this->state[state].active)
1727
GLFragment::Attrib fa (attrib);
1728
int param, function;
1735
param = fa.allocParameters (1);
1737
function = bScreen->getSrcBlurFragmentFunction (texture, param);
1740
fa.addFunction (function);
1742
dx = ((texture->matrix ().xx / 2.1f) * blur) / 65535.0f;
1743
dy = ((texture->matrix ().yy / 2.1f) * blur) / 65535.0f;
1745
(*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1746
param, dx, dy, dx, -dy);
1748
/* bi-linear filtering is required */
1749
mask |= PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
1753
if (this->state[state].active)
1755
GLFragment::Attrib dstFa (fa);
1756
float threshold = (float) this->state[state].threshold;
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;
1763
param = dstFa.allocParameters (3);
1764
unit = dstFa.allocTextureUnits (1);
1766
function = bScreen->getDstBlurFragmentFunction (
1767
texture, param, unit, 0, 0);
1770
dstFa.addFunction (function);
1772
(*GL::activeTexture) (GL_TEXTURE0_ARB + unit);
1773
glBindTexture (bScreen->target, bScreen->texture[0]);
1774
(*GL::activeTexture) (GL_TEXTURE0_ARB);
1776
(*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1778
bScreen->tx, bScreen->ty,
1781
(*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1783
threshold, threshold,
1784
threshold, threshold);
1786
(*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1788
dx, dy, 0.0f, 0.0f);
1791
case BLUR_FILTER_GAUSSIAN:
1792
if (bScreen->opt[BLUR_OPTION_INDEPENDENT_TEX].value ().b ())
1794
/* leave one free texture unit for fragment position */
1795
iTC = MAX (0, GL::maxTextureUnits -
1796
(gWindow->geometry ().texUnits + 1));
1798
iTC = MIN (iTC / 2, bScreen->numTexop);
1801
param = dstFa.allocParameters (2);
1802
unit = dstFa.allocTextureUnits (2);
1804
function = bScreen->getDstBlurFragmentFunction (
1805
texture, param, unit, iTC, gWindow->geometry().texUnits);
1810
dstFa.addFunction (function);
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);
1818
(*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1820
bScreen->ty, 0.0f, 0.0f);
1822
(*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1824
threshold, threshold,
1825
threshold, threshold);
1830
float s_gen[4], t_gen[4], q_gen[4];
1832
for (i = 0; i < 16; i++)
1834
tm[0] = (bScreen->output->width () / 2.0) *
1836
tm[5] = (bScreen->output->height () / 2.0) *
1840
tm[12] = (bScreen->output->width () / 2.0 +
1841
bScreen->output->x1 ()) * bScreen->tx;
1842
tm[13] = (bScreen->output->height () / 2.0 +
1844
bScreen->output->y2 ()) * bScreen->ty;
1850
for (i = 0; i < iTC; i++)
1852
(*GL::activeTexture) (GL_TEXTURE0_ARB +
1853
gWindow->geometry ().texUnits + (i * 2));
1856
rm[13] = bScreen->ty * bScreen->pos[i];
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);
1876
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE,
1878
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE,
1880
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE,
1883
glEnable(GL_TEXTURE_GEN_S);
1884
glEnable(GL_TEXTURE_GEN_T);
1885
glEnable(GL_TEXTURE_GEN_Q);
1887
(*GL::activeTexture) (GL_TEXTURE0_ARB +
1888
gWindow->geometry ().texUnits +
1893
rm[13] = -bScreen->ty * bScreen->pos[i];
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);
1913
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE,
1915
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE,
1917
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE,
1920
glEnable(GL_TEXTURE_GEN_S);
1921
glEnable(GL_TEXTURE_GEN_T);
1922
glEnable(GL_TEXTURE_GEN_Q);
1925
(*GL::activeTexture) (GL_TEXTURE0_ARB);
1930
case BLUR_FILTER_MIPMAP:
1931
param = dstFa.allocParameters (2);
1932
unit = dstFa.allocTextureUnits (1);
1935
bScreen->getDstBlurFragmentFunction (texture, param,
1940
bScreen->opt[BLUR_OPTION_MIPMAP_LOD].value ().f ();
1942
dstFa.addFunction (function);
1944
(*GL::activeTexture) (GL_TEXTURE0_ARB + unit);
1945
glBindTexture (bScreen->target, bScreen->texture[0]);
1946
(*GL::activeTexture) (GL_TEXTURE0_ARB);
1948
(*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1950
bScreen->tx, bScreen->ty,
1953
(*GL::programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
1955
threshold, threshold,
1956
threshold, threshold);
1961
if (this->state[state].clipped ||
1962
(!bScreen->blurOcclusion && !clip.isEmpty ()))
1964
glEnable (GL_STENCIL_TEST);
1966
glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
1967
glStencilFunc (GL_EQUAL, 0x1, ~0);
1969
/* draw region with destination blur */
1970
gWindow->glDrawTexture (texture, dstFa, mask);
1972
glStencilFunc (GL_EQUAL, 0, ~0);
1974
/* draw region without destination blur */
1975
gWindow->glDrawTexture (texture, fa, mask);
1977
glDisable (GL_STENCIL_TEST);
1981
/* draw with destination blur */
1982
gWindow->glDrawTexture (texture, dstFa, mask);
1987
gWindow->glDrawTexture (texture, fa, mask);
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);
2002
for (i = gWindow->geometry().texUnits;
2003
i < gWindow->geometry().texUnits + (2 * iTC); i++)
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);
2010
(*GL::activeTexture) (GL_TEXTURE0_ARB);
2015
gWindow->glDrawTexture (texture, attrib, mask);
2020
BlurScreen::handleEvent (XEvent *event)
2022
Window activeWindow = screen->activeWindow ();
2024
screen->handleEvent (event);
2026
if (screen->activeWindow () != activeWindow)
2030
w = screen->findWindow (activeWindow);
2033
if (opt[BLUR_OPTION_FOCUS_BLUR].value ().b ())
2035
CompositeWindow::get (w)->addDamage ();
2040
w = screen->findWindow (screen->activeWindow ());
2043
if (opt[BLUR_OPTION_FOCUS_BLUR].value ().b ())
2045
CompositeWindow::get (w)->addDamage ();
2051
if (event->type == PropertyNotify)
2055
for (i = 0; i < BLUR_STATE_NUM; i++)
2057
if (event->xproperty.atom == blurAtom[i])
2061
w = screen->findWindow (event->xproperty.window);
2063
BlurWindow::get (w)->update (i);
2070
BlurWindow::resizeNotify (int dx,
2075
if (bScreen->alphaBlur)
2077
if (state[BLUR_STATE_CLIENT].threshold ||
2078
state[BLUR_STATE_DECOR].threshold)
2082
window->resizeNotify (dx, dy, dwidth, dheight);
2087
BlurWindow::moveNotify (int dx,
2091
if (!region.isEmpty ())
2092
region.translate (dx, dy);
2094
window->moveNotify (dx, dy, immediate);
2098
blurPulse (CompAction *action,
2099
CompAction::State state,
2100
CompOption::Vector &options)
2105
xid = CompOption::getIntOptionNamed (options, "window",
2106
screen->activeWindow ());
2108
w = screen->findWindow (xid);
2109
if (w && GL::fragmentProgram)
2111
BLUR_SCREEN (screen);
2115
bs->moreBlur = TRUE;
2117
bw->cWindow->addDamage ();
2124
BlurScreen::matchExpHandlerChanged ()
2126
screen->matchExpHandlerChanged ();
2128
/* match options are up to date after the call to matchExpHandlerChanged */
2129
foreach (CompWindow *w, screen->windows ())
2130
BlurWindow::get (w)->updateMatch ();
2135
BlurScreen::matchPropertyChanged (CompWindow *w)
2137
BlurWindow::get (w)->updateMatch ();
2139
screen->matchPropertyChanged (w);
2142
static CompMetadata *blurMetadata;
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 }
2160
CompOption::Vector &
2161
BlurScreen::getOptions ()
2167
BlurScreen::setOption (const char *name,
2168
CompOption::Value &value)
2173
o = CompOption::findOption (opt, name, &index);
2178
case BLUR_OPTION_BLUR_SPEED:
2181
blurTime = 1000.0f / o->value ().f ();
2185
case BLUR_OPTION_FOCUS_BLUR_MATCH:
2186
case BLUR_OPTION_ALPHA_BLUR_MATCH:
2189
foreach (CompWindow *w, screen->windows ())
2190
BlurWindow::get (w)->updateMatch ();
2193
cScreen->damageScreen ();
2198
case BLUR_OPTION_FOCUS_BLUR:
2202
cScreen->damageScreen ();
2207
case BLUR_OPTION_ALPHA_BLUR:
2210
if (GL::fragmentProgram && o->value ().b ())
2215
cScreen->damageScreen ();
2220
case BLUR_OPTION_FILTER:
2224
cScreen->damageScreen ();
2228
case BLUR_OPTION_GAUSSIAN_RADIUS:
2229
case BLUR_OPTION_GAUSSIAN_STRENGTH:
2230
case BLUR_OPTION_INDEPENDENT_TEX:
2233
if (opt[BLUR_OPTION_FILTER].value ().i () == BLUR_FILTER_GAUSSIAN)
2236
cScreen->damageScreen ();
2241
case BLUR_OPTION_MIPMAP_LOD:
2244
if (opt[BLUR_OPTION_FILTER].value ().i () == BLUR_FILTER_MIPMAP)
2247
cScreen->damageScreen ();
2252
case BLUR_OPTION_SATURATION:
2256
cScreen->damageScreen ();
2260
case BLUR_OPTION_BLUR_OCCLUSION:
2263
blurOcclusion = o->value ().b ();
2265
cScreen->damageScreen ();
2270
return CompOption::setOption (*o, value);
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),
2284
srcBlurFunctions (0),
2285
dstBlurFunctions (0),
2293
if (!blurVTable->getMetadata ()->initOptions (blurOptionInfo,
2294
BLUR_OPTION_NUM, opt))
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);
2305
blurTime = 1000.0f / opt[BLUR_OPTION_BLUR_SPEED].value ().f ();
2306
blurOcclusion = opt[BLUR_OPTION_BLUR_OCCLUSION].value ().b ();
2308
for (int i = 0; i < 2; i++)
2311
glGetIntegerv (GL_STENCIL_BITS, &stencilBits);
2313
compLogMessage ("blur", CompLogLevelWarn,
2314
"No stencil buffer. Region based blur disabled");
2316
/* We need GL_ARB_fragment_program for blur */
2317
if (GL::fragmentProgram)
2318
alphaBlur = opt[BLUR_OPTION_ALPHA_BLUR].value ().b ();
2322
if (GL::fragmentProgram)
2325
GL::getProgramiv (GL_FRAGMENT_PROGRAM_ARB,
2326
GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,
2331
updateFilterRadius ();
2333
ScreenInterface::setHandler (screen, true);
2334
CompositeScreenInterface::setHandler (cScreen, true);
2335
GLScreenInterface::setHandler (gScreen, true);
2339
BlurScreen::~BlurScreen ()
2341
foreach (BlurFunction &bf, srcBlurFunctions)
2342
GLFragment::destroyFragmentFunction (bf.id);
2343
foreach (BlurFunction &bf, dstBlurFunctions)
2344
GLFragment::destroyFragmentFunction (bf.id);
2346
cScreen->damageScreen ();
2349
(*GL::deleteFramebuffers) (1, &fbo);
2351
for (int i = 0; i < 2; i++)
2353
glDeleteTextures (1, &texture[i]);
2357
BlurWindow::BlurWindow (CompWindow *w) :
2358
PrivateHandler<BlurWindow,CompWindow> (w),
2360
gWindow (GLWindow::get (w)),
2361
cWindow (CompositeWindow::get (w)),
2362
bScreen (BlurScreen::get (screen)),
2367
for (int i = 0; i < BLUR_STATE_NUM; i++)
2369
state[i].threshold = 0;
2370
state[i].clipped = false;
2371
state[i].active = false;
2376
update (BLUR_STATE_CLIENT);
2377
update (BLUR_STATE_DECOR);
2382
WindowInterface::setHandler (window, true);
2383
GLWindowInterface::setHandler (gWindow, true);
2386
BlurWindow::~BlurWindow ()
2391
BlurPluginVTable::init ()
2393
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) |
2394
!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) |
2395
!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
2398
getMetadata ()->addFromOptionInfo (blurOptionInfo, BLUR_OPTION_NUM);
2399
getMetadata ()->addFromFile (name ());