chjj / compton

A compositor for X11.
Other
2.25k stars 499 forks source link

[feature request] Invert color #75

Closed MaskRay closed 11 years ago

MaskRay commented 11 years ago

Could someone implement compiz-like color inverting functionality?

richardgv commented 11 years ago
  1. This might be possible, with PictOpDifference?
  2. The performance may not be too great. X Render is much slower than OpenGL.
  3. I can't see why it would be useful. Inverted color doesn't look pleasant at all. And in what case do you want colors to be inverted? To invert color for all inactive windows sounds too scary.
MaskRay commented 11 years ago

Yes, I can only find one use case where inverted color will be helpful: surfing on the Internet with a browser (Firefox, Chromium, Opera, ...). Darkening the page make reading a pleasure.

Besides, I'd like to recommend redshift (http://jonls.dk/redshift/) which adjusts the color temperature.

richardgv commented 11 years ago

Yes, I can only find one use case where inverted color will be helpful: surfing on the Internet with a browser (Firefox, Chromium, Opera, ...). Darkening the page make reading a pleasure.

Adding a feature takes efforts, and it could have unexpected negative effects (e.g. enlarged binary). So please think carefully about whether you really need a feature before you submit a feature request.

If what you want is to invert colors for browsers only, you could consider, for instance, "High Contrast" for Chrome or "Blank Your Monitor + Easy Reading" for Firefox.

Besides, I'd like to recommend redshift (http://jonls.dk/redshift/) which adjusts the color temperature.

Redshift uses X Randr to adjust the color temperature of the whole screen (instead of individual windows). You could adjust the options yourself with xrandr. That's a different thing.

MaskRay commented 11 years ago

On 03/01/13 at 08:53pm, Richard Grenville wrote:

Yes, I can only find one use case where inverted color will be helpful: surfing on the Internet with a browser (Firefox, Chromium, Opera, ...). Darkening the page make reading a pleasure.

Adding a feature takes efforts, and it could have unexpected negative effects (e.g. enlarged binary). So please think carefully about whether you really need a feature before you submit a feature request.

If what you want is to invert colors for browsers only, you could consider, for instance, "High Contrast" for Chrome or "Blank Your Monitor + Easy Reading" for Firefox.

Thanks for your advice. I've already investigated several addons out there and unfortunately found they merely related to CSS so the diversity of coloration is completely broken (oh, I'd confess that inverted color looks also strange but is a little better). Inverted color will be a convenient feature as there is no easy way to adjust color output from the browser. If adding such feature takes too much effort, please close this issue.

Besides, I'd like to recommend redshift (http://jonls.dk/redshift/) which adjusts the color temperature.

Redshift uses X Randr to adjust the color temperature of the whole screen (instead of individual windows). You could adjust the options yourself with xrandr. That's a different thing.


Reply to this email directly or view it on GitHub: https://github.com/chjj/compton/issues/75#issuecomment-11872536

richardgv commented 11 years ago

Inverted color will be a convenient feature as there is no easy way to adjust color output from the browser. If adding such feature takes too much effort, please close this issue.

Alright, I will try implementing this after I finish the new condition format code, as I suppose the color inversion is only really usable if combined with the new, more flexible, condition format. Well, god know how much time that will take. :-S

richardgv commented 11 years ago

@MaskRay:

  1. Well, I didn't finish the new condition format code in time. I came with the feature you want firstly, because it's easier to implement. :-)
  2. Please pull from richardgv-dev branch, build it, and use this to invert colors of all Firefox windows:

    compton --invert-color-include 'g:e:Firefox'`
  3. You have been warned, the performance is a huge issue. Triple painting should be pretty slow. Unfortunately I do not know a faster solution right now.
  4. Shadow color is not inverted. You won't like that too much, will you?
  5. I would really like to hear suggestions regarding our color inversion method. Currently we:

    1. Paint window content to a temporary buffer;
    2. Do PictOpDifference between a white picture and the temporary buffer;
    3. For ARGB windows, the pixel alpha values are destroyed in PictOpDifference, so we copy the old pixel alpha over with PictOpInReverse;
    4. Use the temporary buffer for painting.

    So effectively we have 3x / 4x painting job. Any better ways?

MaskRay commented 11 years ago

On 12/01/13 at 07:06am, Richard Grenville wrote:

@MaskRay:

  1. Well, I didn't finish the new condition format code in time. I came with the feature you want firstly, because it's easier to implement. :-)
  2. Please pull from richardgv-dev branch, build it, and use this to invert colors of all Firefox windows:

    compton --invert-color-include 'g:e:Firefox'`

So excited to see this feature being added in the `richardgb-dev' branch (commit 2165c42d2792afdc544af142313470eb9810e62f)! But I could not get it work with either

compton --invert-color-include 'g:e:Firefox'

or

compton --invert-color-include 'g:e:XTerm'

I've also fiddled with g:p:.*',g:e:URxvt' and so on in two tiling window managers (xmonad',i3'), but have not get good luck.

  1. You have been warned, the performance is a huge issue. Triple painting should be pretty slow. Unfortunately I do not know a faster solution right now.
  2. Shadow color is not inverted. You won't like that too much, will you?
  3. I would really like to hear suggestions regarding our color inversion method. Currently we:

    1. Paint window content to a temporary buffer;
    2. Do PictOpDifference between a white picture and the temporary buffer;
    3. For ARGB windows, the pixel alpha values are destroyed in PictOpDifference, so we copy the old pixel alpha over with PictOpInReverse;
    4. Use the temporary buffer for painting.

    So effectively we have 3x / 4x painting job. Any better ways?

I know little about these but I will be glad to report my feeling (CPU usage according to `htop' ?).

xiaq commented 11 years ago

No luck here with compton --invert-color-include 'g:e:Firefox' either. I also tested with Leafpad, a super-simple GTK2 application, with compton --invert-color-include 'g:ai:leafpad', and it doesn't work either.

In case the underlying WM may affect the issue, I'm using herbstluftwm. @MaskRay you are using xmonad right?

richardgv commented 11 years ago

Sorry, I missed a single line last night, and the result is --invert-color-include only works if another blacklist option (e.g. --shadow-exclude) is enabled, too. :-S e60fe72 should fix the problem. Please pull from richardgv-dev branch and test.

I really didn't expect many would be interested in this feature...

I saw sometimes when a window is created/mapped, with color inverted, it flickers and gets fully white for a very short period of time. Do you see the problem, too? With nvidia-drivers-310.19?

If it still does not work, it could be a failure in window name fetching.

I know little about these but I will be glad to report my feeling (CPU usage according to `htop' ?).

My primary concern is on GPU. It happened once on #59: I added the blur feature, he said it's too slow to use. I have a GTX 670 myself, so most performance issues are unfortunately invisible for me.

richardgv commented 11 years ago

Code of this feature has been merged into master branch. Could any of you confirm whether it works?

MaskRay commented 11 years ago

On 28/01/13 at 06:43am, Richard Grenville wrote:

Code of this feature has been merged into master branch. Could any of you confirm whether it works?

This feature works though it is very CPU-intensive... htop' saysCPU%' of the process named `X :0' is about 90%.

richardgv commented 11 years ago

This feature works though it is very CPU-intensive... htop' saysCPU%' of the process named `X :0' is about 90%.

Indeed, much worse than what I thought. Here's a quick-'n'-dirty patch to reduce the region we do PictOpDifference on. Please pull from richardgv-dev branch, apply the patch, and see how it goes. My tests show at least 50% reduction in CPU load when rapidly moving windows.

diff --git a/src/compton.c b/src/compton.c
index cbb5e7b..1efb631 100644
--- a/src/compton.c
+++ b/src/compton.c
@@ -1360,7 +1360,7 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
  * Paint a window itself and dim it if asked.
  */
 static inline void
-win_paint_win(session_t *ps, win *w, Picture tgt_buffer) {
+win_paint_win(session_t *ps, win *w, Picture tgt_buffer, XserverRegion reg_paint) {
   int x = w->a.x;
   int y = w->a.y;
   int wid = w->widthb;
@@ -1374,6 +1374,14 @@ win_paint_win(session_t *ps, win *w, Picture tgt_buffer) {
   if (w->invert_color) {
     Picture newpict = win_build_picture(ps, w, w->a.visual);
     if (newpict) {
+      // Apply clipping region to save some CPU
+      if (reg_paint) {
+        XserverRegion reg = copy_region(ps, reg_paint);
+        XFixesTranslateRegion(ps->dpy, reg, -x, -y);
+        XFixesSetPictureClipRegion(ps->dpy, newpict, 0, 0, reg);
+        free_region(ps, &reg);
+      }
+
       XRenderComposite(ps->dpy, PictOpSrc, pict, None,
           newpict, 0, 0, 0, 0, 0, 0, wid, hei);
       XRenderComposite(ps->dpy, PictOpDifference, ps->white_picture, None,
@@ -1602,7 +1610,7 @@ paint_all(session_t *ps, XserverRegion region, win *t) {
       }

       // Painting the window
-      win_paint_win(ps, w, ps->tgt_buffer);
+      win_paint_win(ps, w, ps->tgt_buffer, reg_paint);
     }

     check_fade_fin(ps, w);

sysprof shows libpixman.so and nVidia driver consume most CPU resources when color inversion is on. But once I lift the PictOpDifference line, the CPU load get greatly reduced. So seemingly X isn't particularly efficient when doing PictOpDifference.

If the CPU load is still too high with the patch, --sw-opti or --vsync, which reduces paint frequency, might be helpful.

MaskRay commented 11 years ago

On 28/01/13 at 07:21am, Richard Grenville wrote:

This feature works though it is very CPU-intensive... htop' saysCPU%' of the process named `X :0' is about 90%.

Indeed, much worse than what I thought. Here's a quick-'n'-dirty patch to reduce the region we do PictOpDifference on. Please pull from richardgv-dev branch, apply the patch, and see how it goes. My tests show at least 50% reduction in CPU load when rapidly moving windows.

diff --git a/src/compton.c b/src/compton.c
index cbb5e7b..1efb631 100644
--- a/src/compton.c
+++ b/src/compton.c
@@ -1360,7 +1360,7 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
  * Paint a window itself and dim it if asked.
  */
 static inline void
-win_paint_win(session_t *ps, win *w, Picture tgt_buffer) {
+win_paint_win(session_t *ps, win *w, Picture tgt_buffer, XserverRegion reg_paint) {
   int x = w->a.x;
   int y = w->a.y;
   int wid = w->widthb;
@@ -1374,6 +1374,14 @@ win_paint_win(session_t *ps, win *w, Picture tgt_buffer) {
   if (w->invert_color) {
     Picture newpict = win_build_picture(ps, w, w->a.visual);
     if (newpict) {
+      // Apply clipping region to save some CPU
+      if (reg_paint) {
+        XserverRegion reg = copy_region(ps, reg_paint);
+        XFixesTranslateRegion(ps->dpy, reg, -x, -y);
+        XFixesSetPictureClipRegion(ps->dpy, newpict, 0, 0, reg);
+        free_region(ps, &reg);
+      }
+
       XRenderComposite(ps->dpy, PictOpSrc, pict, None,
           newpict, 0, 0, 0, 0, 0, 0, wid, hei);
       XRenderComposite(ps->dpy, PictOpDifference, ps->white_picture, None,
@@ -1602,7 +1610,7 @@ paint_all(session_t *ps, XserverRegion region, win *t) {
       }

       // Painting the window
-      win_paint_win(ps, w, ps->tgt_buffer);
+      win_paint_win(ps, w, ps->tgt_buffer, reg_paint);
     }

     check_fade_fin(ps, w);

sysprof shows libpixman.so and nVidia driver consume most CPU resources when color inversion is on. But once I lift the PictOpDifference line, the CPU load get greatly reduced. So seemingly X isn't particularly efficient when doing PictOpDifference.

If the CPU load is still too high with the patch, --sw-opti or --vsync, which reduces paint frequency, might be helpful.

./compton -i 0.8 -cC --invert-color-include 'g:e:Google-chrome'

fails to invert colors with the latest commit from the richardgv-dev' branch (commit 6d36ef2d0fefa79a04a73921ce584d2bb03d94f2). However, It works with themaster' branch.

richardgv commented 11 years ago

fails to invert colors with the latest commit from the richardgv-dev' branch (commit 6d36ef2). However, It works with themaster' branch.

  1. We changed matching system, as described in 6d36ef2. The new system might be buggy.
  2. I have www-client/google-chrome-25.0.1364.45_beta178221 installed. The same command works fine here.
  3. Are there any warning messages emitted?
  4. Does this work?
   compton --invert-color-include 'class_i *= "google-chrome"'
  1. If it still does not work, please try build with some debugging options, and show me the output when running compton:

    make clean; CFLAGS='-ggdb -DDEBUG_C2 -DDEBUG_WINDATA' make
  2. Do you have a configuration file? If you do, please show me the contents.
richardgv commented 11 years ago
  1. Please read my reply above firstly. Note I edited it for a few times after submission, and please read from the GitHub web interface instead of in your mailbox.
  2. Correction: Looks like it's --sw-opti that caused the 50% performance boost, not my patch -- but my patch should help in many cases.
  3. I've merged the patch above to richardgv-dev branch.
MaskRay commented 11 years ago
  1. We changed matching system, as described in 6d36ef2. The new system might be buggy.
  2. I have www-client/google-chrome-25.0.1364.45_beta178221 installed. The same command works fine here.
  3. Are there any warning messages emitted?
  4. Does this work?

    compton --invert-color-include 'class_i *= "google-chrome"'

  5. If it still does not work, please try build with some debugging options, and show me the output:

    make clean; CFLAGS='-ggdb -DDEBUG_C2 -DDEBUG_WINDATA' make
  6. Do you have a configuration file? If you do, please show me the contents.

I have www-client/google-chrome-25.0.1364.45_beta178221 emerged and tested commit 42e17cb4e9ed6f05f09d8ed612d7c9ef08468def and found it strange that make does not work.

However, CFLAGS='-ggdb -DDEBUG_C2 -DDEBUG_WINDATA' make does and the performance is greatly improved!

MaskRay commented 11 years ago

This is the output of compton compiled with CFLAGS='-ggdb -DDEBUG_C2 -DDEBUG_WINDATA': http://bpaste.net/show/73563/

richardgv commented 11 years ago

I'm in #compton on FreeNode right now. Please come here if possible. I suppose synchronous communication is more efficient than talking here.

I have www-client/google-chrome-25.0.1364.45_beta178221 emerged and tested commit 42e17cb and found it strange that make does not work.

make does not work? You mean, it does not compile, or the build you got does not run, or the build you got just doesn't match correctly? Timing issue?

However, CFLAGS='-ggdb -DDEBUG_C2 -DDEBUG_WINDATA' make does and the performance is greatly improved!

Oh, glad to see that. :-)

This is the output of compton compiled with CFLAGS='-ggdb -DDEBUG_C2 -DDEBUG_WINDATA'

It shows everything is right... But you got the output when the program works correctly, right?

richardgv commented 11 years ago

We discussed on #compton at FreeNode about the matching issue. According to his report, he uses gcc-4.7.0, and this problems appears only when using gcc together with -O2. I tried debugging the binary he provided, and the result is I found cond parameter of c2_parse_once() is not passed correctly to the function. The value of the pointers in cond are correct, but cond.isbranch is detected true while it should be false. We use a bit field for isbranch, and gcc-4.7.0 has quite some bugs handling bit fields. In particular, I suspect it's Bug 53438 – Bitfield store replaced with full-byte store in gcc that triggered the problem. My current recommendation is to use clang or >=gcc-4.7.2 to build compton.

richardgv commented 11 years ago

If any of you are still having performance problems, I've added OpenGL backend to compton (8ffcf1c in richardgv-dev branch, --opengl). It should move all color inversion jobs to GPU.

anderspapitto commented 11 years ago

Hello @richardgv - I've just begun to make use of this feature, and I'm feeling the performance hit - it takes about an extra second to render a workspace with a color-inverted application.

I want to see if I can spot any way to reduce this overhead, but I'm not familiar with the ecosystem - for example, I don't know who provides this PictOpDifference function -it could be the Xlib or Xcb headers, or someone else entirely. Would you mind linking me to the relevant source/api/documentation of what compton is build on top of? I haven't had much luck with google.

richardgv commented 11 years ago

@anderspapitto:

Hello richardgv - I've just begun to make use of this feature, and I'm feeling the performance hit - it takes about an extra second to render a workspace with a color-inverted application.

Use GLX backend. That's the only viable solution we know currently, and it's very fast, unless you don't have a sane driver.

I want to see if I can spot any way to reduce this overhead, but I'm not familiar with the ecosystem - for example, I don't know who provides this PictOpDifference function -it could be the Xlib or Xcb headers, or someone else entirely. Would you mind linking me to the relevant source/api/documentation of what compton is build on top of? I haven't had much luck with google.

For X Render backend, it's X Render that provided the function. Its protocol prototype is on < http://cgit.freedesktop.org/xorg/proto/renderproto/tree/renderproto.txt >. Its implementation is in xorg-server (or XFree86, if you still have it :-D ), pixman, and your driver. I assume the primary reason of the slowness is your driver (or xorg-server?) decides to let CPU handle all the work, through pixman, which is highly inefficient, and this is beyond our control. We tried to reduce the delay, and it's acceptable on high-end systems, but I don't think it's necessary to dig further as there's no apparent fix on our side and GLX backend is a great alternative.

For GLX backend, we use glLogicOp(GL_COPY_INVERTED).

anderspapitto commented 11 years ago

@richardgv thanks for the quick reply.

I am using glx - or at least I see in /var/log/Xorg.0.log that it is loaded. I suppose it's possible that it isn't being used by compton. Or, as you say, it could be the driver - I'm using nouveou, which I understand is slower, as the proprietary nvidia drivers don't function in my setup.

I took a look at the call to glLogic, and I see that it's wrapped in a check of GL_BLEND

 if (!glIsEnabled(GL_BLEND)) {
    glEnable(GL_COLOR_LOGIC_OP);
    glLogicOp(GL_COPY_INVERTED);
} 

Is there a way I can ensure that I have this other feature (GL_BLEND) disabled, so that I don't fall into one of the slow code paths?

richardgv commented 11 years ago

I am using glx - or at least I see in /var/log/Xorg.0.log that it is loaded. I suppose it's possible that it isn't being used by compton. Or, as you say, it could be the driver - I'm using nouveou, which I understand is slower, as the proprietary nvidia drivers don't function in my setup.

No, that is not correct. compton supports two backends, X Render and GLX, and it defaults to X Render even when you have GLX extension loaded on X server. (This is for reliability, by the way, since on certain broken drivers, GLX may perform poorly.) To switch to GLX backend, use --backend glx in commandline arguments, or backend = "glx" in your configuration file. (To verify if you have GLX backend in use, run compton with --vsync opengl-swc: If it's under XRender backend you get a warning on stderr.)

Color inversion performs well even in those quite low end Intel IGPs, so it isn't nouveau that matters, I suppose.

I took a look at the call to glLogic, and I see that it's wrapped in a check of GL_BLEND Is there a way I can ensure that I have this other feature (GL_BLEND) disabled, so that I don't fall into one of the slow code paths?

Yes, by ensuring all your windows with inverted colors are opaque. But GL_BLEND is moderately fast on any sort of modern hardware and sane driver. So... You may waste your precious time by looking around the core functions of compton, as they require some knowledge about X and OpenGL to understand. Just report any issues to us and we are willing to help. Our IRC channel (FreeNode/#compton) might be a good place to ask quick questions, as well.

anderspapitto commented 10 years ago

Alright, many thanks @richardgv. Apologies for nosing around a bit - I'm just trying to pick up some background knowledge as I configure my system.

richardgv commented 10 years ago

@anderspapitto:

But, does --backend glx actually help for you?

anderspapitto commented 10 years ago

yes - I no longer notice any delay (with a fullscreen, color-inverted, transparent firefox)