2
* Copyright (c) 2006 Darryll Truchan <moppsy@comcast.net>
4
* Pixel shader negating by Dennis Kasprzyk <onestone@beryl-project.org>
5
* Usage of matches by Danny Baumann <maniac@beryl-project.org>
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 2
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25
using namespace GLFragment;
27
COMPIZ_PLUGIN_20090315 (neg, NegPluginVTable);
34
/* toggle window negative flag */
37
/* check exclude list */
38
if (ns->optionGetExcludeMatch ().evaluate (window))
41
/* cause repainting */
42
cWindow->addDamage ();
45
gWindow->glDrawTextureSetEnabled (this, true);
47
gWindow->glDrawTextureSetEnabled (this, false);
51
NegScreen::toggle (CompAction *action,
52
CompAction::State state,
53
CompOption::Vector options,
58
foreach (CompWindow *w, screen->windows ())
59
NegWindow::get (w)->toggle ();
60
/* toggle screen negative flag */
68
xid = CompOption::getIntOptionNamed (options, "window");
69
w = screen->findWindow (xid);
71
NegWindow::get (w)->toggle ();
78
NegScreen::getFragmentFunction (GLTexture *texture,
83
if (alpha && negAlphaFunction)
84
handle = negAlphaFunction;
85
else if (!alpha && negFunction)
94
data.addTempHeaderOp ("neg");
96
if (texture->target () == GL_TEXTURE_2D)
97
target = COMP_FETCH_TARGET_2D;
99
target = COMP_FETCH_TARGET_RECT;
101
data.addFetchOp ("output", NULL, target);
105
data.addDataOp ("RCP neg.a, output.a;");
106
data.addDataOp ("MAD output.rgb, -neg.a, output, 1.0;");
109
data.addDataOp ("SUB output.rgb, 1.0, output;");
112
data.addDataOp ("MUL output.rgb, output.a, output;");
114
data.addColorOp ("output", "output");
119
handle = data.createFragmentFunction ("neg");
122
negAlphaFunction = handle;
124
negFunction = handle;
131
NegWindow::glDrawTexture (GLTexture *texture,
132
GLFragment::Attrib &attrib,
135
GLTexture::Filter filter;
137
GLTexture *tex = NULL;
143
if (ns->optionGetNegDecorations ())
151
for (unsigned int i = 0; i < gWindow->textures ().size (); i++)
153
tex = gWindow->textures ()[i];
154
doNeg = (texture->name () == tex->name ());
163
/* Fragment program negation */
164
if (GL::fragmentProgram)
166
GLFragment::Attrib fa = attrib;
170
if (texture->name () == tex->name ()) /* Not a decoration */
171
alpha = window->alpha ();
173
function = ns->getFragmentFunction (texture, alpha);
175
fa.addFunction (function);
177
gWindow->glDrawTexture (texture, fa, mask);
179
else /* Texture manipulation negation */
181
/* this is for the most part taken from paint.c */
183
if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
184
filter = ns->gScreen->filter (WINDOW_TRANS_FILTER);
185
else if (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
186
filter = ns->gScreen->filter (SCREEN_TRANS_FILTER);
188
filter = ns->gScreen->filter (NOTHING_TRANS_FILTER);
190
/* if we can adjust saturation, even if it's just on and off */
191
if (GL::canDoSaturated && attrib.getSaturation () != COLOR)
195
/* if the paint mask has this set we want to blend */
196
if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
199
/* enable the texture */
200
texture->enable (filter);
202
/* texture combiner */
203
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
204
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
205
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
206
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
207
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);
210
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
211
GL_ONE_MINUS_SRC_COLOR);
213
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
214
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
216
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
217
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
218
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
220
glColor4f (1.0f, 1.0f, 1.0f, 0.5f);
222
/* make another texture active */
223
GL::activeTexture (GL_TEXTURE1_ARB);
225
/* enable that texture */
226
texture->enable (filter);
228
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
229
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
230
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
231
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
232
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
233
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
235
/* if we can do saturation that is in between min and max */
236
if (GL::canDoSlightlySaturated && attrib.getSaturation () > 0)
238
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
239
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
240
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
242
constant[0] = 0.5f + 0.5f * RED_SATURATION_WEIGHT;
243
constant[1] = 0.5f + 0.5f * GREEN_SATURATION_WEIGHT;
244
constant[2] = 0.5f + 0.5f * BLUE_SATURATION_WEIGHT;
247
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
249
/* make another texture active */
250
GL::activeTexture (GL_TEXTURE2_ARB);
252
/* enable that texture */
253
texture->enable (filter);
255
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
256
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
257
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
258
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
259
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);
262
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
263
GL_ONE_MINUS_SRC_COLOR);
265
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
266
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
268
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
269
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
270
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
273
constant[3] = attrib.getSaturation () / 65535.0f;
275
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
277
/* if we are not opaque or not fully bright */
278
if (attrib.getOpacity () < OPAQUE ||
279
attrib.getBrightness () != BRIGHT)
281
/* make another texture active */
282
GL::activeTexture (GL_TEXTURE3_ARB);
284
/* enable that texture */
285
texture->enable (filter);
288
constant[3] = attrib.getOpacity () / 65535.0f;
289
constant[0] = constant[1] = constant[2] =
290
constant[3] * attrib.getBrightness () / 65535.0f;
292
glTexEnvfv(GL_TEXTURE_ENV,
293
GL_TEXTURE_ENV_COLOR, constant);
295
glTexEnvf(GL_TEXTURE_ENV,
296
GL_TEXTURE_ENV_MODE, GL_COMBINE);
298
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
299
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
300
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
301
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
303
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB,
306
glTexEnvf (GL_TEXTURE_ENV,
307
GL_COMBINE_ALPHA, GL_MODULATE);
308
glTexEnvf(GL_TEXTURE_ENV,
309
GL_SOURCE0_ALPHA, GL_PREVIOUS);
310
glTexEnvf(GL_TEXTURE_ENV,
311
GL_SOURCE1_ALPHA, GL_CONSTANT);
312
glTexEnvf(GL_TEXTURE_ENV,
313
GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
314
glTexEnvf(GL_TEXTURE_ENV,
315
GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
317
/* draw the window geometry */
318
gWindow->glDrawGeometry ();
320
/* disable the current texture */
323
/* set texture mode back to replace */
324
glTexEnvi (GL_TEXTURE_ENV,
325
GL_TEXTURE_ENV_MODE, GL_REPLACE);
327
/* re-activate last texture */
328
GL::activeTexture (GL_TEXTURE2_ARB);
332
/* fully opaque and bright */
334
/* draw the window geometry */
335
gWindow->glDrawGeometry ();
338
/* disable the current texture */
341
/* set the texture mode back to replace */
342
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
344
/* re-activate last texture */
345
GL::activeTexture (GL_TEXTURE1_ARB);
349
/* fully saturated or fully unsaturated */
351
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
352
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
353
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
354
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
355
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
358
constant[3] = attrib.getOpacity () / 65535.0f;
359
constant[0] = constant[1] = constant[2] =
360
constant[3] * attrib.getBrightness () / 65535.0f;
363
0.5f + 0.5f * RED_SATURATION_WEIGHT * constant[0];
365
0.5f + 0.5f * GREEN_SATURATION_WEIGHT * constant[1];
367
0.5f + 0.5f * BLUE_SATURATION_WEIGHT * constant[2];
369
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
371
/* draw the window geometry */
372
gWindow->glDrawGeometry ();
375
/* disable the current texture */
378
/* set the texture mode back to replace */
379
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
381
/* re-activate last texture */
382
GL::activeTexture (GL_TEXTURE0_ARB);
384
/* disable that texture */
387
/* set the default color */
388
glColor4usv (defaultColor);
390
/* set screens texture mode back to replace */
391
ns->gScreen->setTexEnvMode (GL_REPLACE);
393
/* if it's a translucent window, disable blending */
394
if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
395
glDisable (GL_BLEND);
399
/* no saturation adjustments */
401
/* enable the current texture */
402
texture->enable (filter);
404
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
405
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
406
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
409
glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB,
410
GL_ONE_MINUS_SRC_COLOR);
412
/* we are not opaque or fully bright */
413
if ((mask & PAINT_WINDOW_TRANSLUCENT_MASK) ||
414
attrib.getBrightness () != BRIGHT)
418
/* enable blending */
422
constant[3] = attrib.getOpacity () / 65535.0f;
423
constant[0] = constant[1] = constant[2] =
424
constant[3] * attrib.getBrightness () / 65535.0f;
426
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
427
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
428
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
429
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
430
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
433
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
434
GL_ONE_MINUS_SRC_COLOR);
436
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
437
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
438
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
439
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
440
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
441
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
442
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
444
/* draw the window geometry */
445
gWindow->glDrawGeometry ();
447
/* disable blending */
448
glDisable (GL_BLEND);
452
/* no adjustments to saturation, brightness or opacity */
454
/* draw the window geometry */
455
gWindow->glDrawGeometry ();
458
/* disable the current texture */
461
/* set the screens texture mode back to replace */
462
ns->gScreen->setTexEnvMode (GL_REPLACE);
469
gWindow->glDrawTexture (texture, attrib, mask);
474
NegScreen::optionChanged (CompOption *opt,
475
NegOptions::Options num)
479
case NegOptions::NegMatch:
480
case NegOptions::ExcludeMatch:
482
foreach (CompWindow *w, screen->windows ())
487
isNowNeg = optionGetNegMatch ().evaluate (w);
488
isNowNeg = isNowNeg && !optionGetExcludeMatch ().evaluate (w);
490
if (isNowNeg && isNeg && !nw->isNeg)
492
else if (!isNowNeg && nw->isNeg)
497
case NegOptions::NegDecorations:
499
foreach (CompWindow *w, screen->windows ())
500
if (NegWindow::get (w)->isNeg)
501
NegWindow::get (w)->cWindow->addDamage ();
508
NegScreen::NegScreen (CompScreen *screen) :
509
PluginClassHandler <NegScreen, CompScreen> (screen),
512
negAlphaFunction (0),
514
gScreen (GLScreen::get (screen))
516
optionSetWindowToggleKeyInitiate (boost::bind (&NegScreen::toggle, this,
519
optionSetScreenToggleKeyInitiate (boost::bind (&NegScreen::toggle, this,
523
optionSetNegMatchNotify (boost::bind (&NegScreen::optionChanged, this,
525
optionSetExcludeMatchNotify (boost::bind (&NegScreen::optionChanged, this,
527
optionSetNegDecorationsNotify (boost::bind (&NegScreen::optionChanged, this,
533
NegWindow::postLoad ()
537
cWindow->addDamage ();
538
gWindow->glDrawTextureSetEnabled (this, true);
543
NegWindow::NegWindow (CompWindow *window) :
544
PluginClassHandler <NegWindow, CompWindow> (window),
545
PluginStateWriter <NegWindow> (this, window->id ()),
547
cWindow (CompositeWindow::get (window)),
548
gWindow (GLWindow::get (window)),
551
GLWindowInterface::setHandler (gWindow, false);
555
/* Taken from ObjectAdd, since there is no equavilent
556
* we check for screenNeg == true in ctor */
558
if (ns->isNeg && ns->optionGetNegMatch ().evaluate (window))
562
NegWindow::~NegWindow ()
564
writeSerializedData ();
568
NegPluginVTable::init ()
570
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
571
!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
572
!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))